Browse Source

fix(ssr): better handle v-html hydration

fix #6519
dev
Evan You 7 years ago
parent
commit
0f00f8fc2b
  1. 57
      src/core/vdom/patch.js
  2. 26
      test/unit/modules/vdom/patch/hydration.spec.js

57
src/core/vdom/patch.js

@ -547,27 +547,46 @@ export function createPatchFunction (backend) {
if (!elm.hasChildNodes()) {
createChildren(vnode, children, insertedVnodeQueue)
} else {
let childrenMatch = true
let childNode = elm.firstChild
for (let i = 0; i < children.length; i++) {
if (!childNode || !hydrate(childNode, children[i], insertedVnodeQueue)) {
childrenMatch = false
break
// v-html and domProps: innerHTML
if (isDef(i = data) && isDef(i = i.domProps) && isDef(i = i.innerHTML)) {
if (i !== elm.innerHTML) {
/* istanbul ignore if */
if (process.env.NODE_ENV !== 'production' &&
typeof console !== 'undefined' &&
!bailed
) {
bailed = true
console.warn('Parent: ', elm)
console.warn('server innerHTML: ', i)
console.warn('client innerHTML: ', elm.innerHTML)
}
return false
}
childNode = childNode.nextSibling
}
// if childNode is not null, it means the actual childNodes list is
// longer than the virtual children list.
if (!childrenMatch || childNode) {
if (process.env.NODE_ENV !== 'production' &&
typeof console !== 'undefined' &&
!bailed
) {
bailed = true
console.warn('Parent: ', elm)
console.warn('Mismatching childNodes vs. VNodes: ', elm.childNodes, children)
} else {
// iterate and compare children lists
let childrenMatch = true
let childNode = elm.firstChild
for (let i = 0; i < children.length; i++) {
if (!childNode || !hydrate(childNode, children[i], insertedVnodeQueue)) {
childrenMatch = false
break
}
childNode = childNode.nextSibling
}
// if childNode is not null, it means the actual childNodes list is
// longer than the virtual children list.
if (!childrenMatch || childNode) {
/* istanbul ignore if */
if (process.env.NODE_ENV !== 'production' &&
typeof console !== 'undefined' &&
!bailed
) {
bailed = true
console.warn('Parent: ', elm)
console.warn('Mismatching childNodes vs. VNodes: ', elm.childNodes, children)
}
return false
}
return false
}
}
}

26
test/unit/modules/vdom/patch/hydration.spec.js

@ -297,4 +297,30 @@ describe('vdom patch: hydration', () => {
done()
}, 50)
})
it('should hydrate v-html with children', () => {
const dom = createMockSSRDOM('<span>foo</span>')
new Vue({
data: {
html: `<span>foo</span>`
},
template: `<div v-html="html">hello</div>`
}).$mount(dom)
expect('not matching server-rendered content').not.toHaveBeenWarned()
})
it('should warn mismatching v-html', () => {
const dom = createMockSSRDOM('<span>bar</span>')
new Vue({
data: {
html: `<span>foo</span>`
},
template: `<div v-html="html">hello</div>`
}).$mount(dom)
expect('not matching server-rendered content').toHaveBeenWarned()
})
})

Loading…
Cancel
Save