vue
vue copied to clipboard
SSR fails to render component inside v-else of a v-if with v-html
Version
2.6.11
Reproduction link
https://github.com/tuomassalo/vue-ssr-v-html-bug
Steps to reproduce
- clone the repo
- run
npm run dev - open
localhost:8080 - observe Console log.
What is expected?
I expect SSR to render "bar: Bar!", as the client-side does.
Or, I'd like to get an eslint warning that this is a bad idea (if that is the problem).
What is actually happening?
App.vue fails to render bar-component on the server. Instead, it outputs <bar-component></bar-component>, and the dev server gives the warning "The client-side rendered virtual DOM tree is not matching server-rendered content."
The key part of App.vue is this:
<div v-if="foo" v-html="'Foo.'"/>
<div v-else>
bar: <bar-component/>
</div>
My original component was naturally longer. I ran into this problem after changing the v-if line from something like:
<div v-if="foo">{{ foo }}</div>
To:
<div v-if="foo" v-html="foo"/>
... which seemed innocuous to me.
Finally, apologies for posting a very possible duplicate.
A workaround is using a template tag:
<div id="app">
<template v-if="foo" >
<div v-html="'Foo.'" key="hey"/>
</template>
<div v-else>
bar: <BarComponent />
</div>
</div>
For SSR repros, it's usually easier to do them with the bare minimum. Here is an example:
const Vue = require('vue')
const BarComponent = {
template: `
<div>Bar!</div>
`,
}
const app = new Vue({
template: `
<div id="app">
<div v-if="foo" v-html="'Foo.'" key="hey"/>
<div v-else>
bar: <BarComponent />
</div>
</div>
`,
data: () => ({ foo: false }),
components: { BarComponent },
})
const renderer = require('vue-server-renderer').createRenderer()
renderer.renderToString(app, (err, html) => {
if (err) throw err
console.log(html)
})
It could also help anybody picking up the issue
me too
having the same issue!
I also ran into an issue and spent half a day to figure out what was going on. Finally, I feel like a fool but:
<div v-if="smth === true" v-html="html"></div>
<component v-else ... /> <----- doesn't work
// but...
<div v-if="smth === true" v-html="html"></div>
<component v-if="smth !== true" /> <----- this works
Hope this helps someone who stuck with that too.
I also ran into an issue and spent half a day to figure out what was going on. Finally, I feel like a fool but:
<div v-if="smth === true" v-html="html"></div> <component v-else ... /> <----- doesn't work // but... <div v-if="smth === true" v-html="html"></div> <component v-if="smth !== true" /> <----- this worksHope this helps someone who stuck with that too.
this does work, but how? can someone please explain what's going on here?
when I wrote this it worked
<div v-if="colorModeIcon">
<Icon @click="switchColorMode" :name="colorModeIcon" />
</div>
<div v-if="!colorModeIcon"> // <- work
<Icon name="line-md:loading-twotone-loop" />
</div>
but this does not
<div v-if="colorModeIcon">
<Icon @click="switchColorMode" :name="colorModeIcon" />
</div>
<div v-else> // <- don't work
<Icon name="line-md:loading-twotone-loop" />
</div>
I'm also having this problem with Nuxt .... strange