mirror of https://github.com/vuejs/core.git
fix(hydration): fix tagName access eeror on comment/text node hydration mismatch
fix #9531
This commit is contained in:
parent
405f34587a
commit
dd8a0cf5dc
|
@ -75,6 +75,16 @@ describe('SSR hydration', () => {
|
||||||
expect(vnode.el.nodeType).toBe(8) // comment
|
expect(vnode.el.nodeType).toBe(8) // comment
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('comment (real left square bracket)', () => {
|
||||||
|
const { vnode, container } = mountWithHydration(
|
||||||
|
`<div><span>foo</span><!--hello--></div>`,
|
||||||
|
() => h('div', [h('span', 'foo'), createCommentVNode('hello')])
|
||||||
|
)
|
||||||
|
expect(vnode.el).toBe(container.firstChild)
|
||||||
|
expect(container.innerHTML).toBe('<div><span>foo</span><!--hello--></div>')
|
||||||
|
expect(`Hydration node mismatch`).not.toHaveBeenWarned()
|
||||||
|
})
|
||||||
|
|
||||||
test('static', () => {
|
test('static', () => {
|
||||||
const html = '<div><span>hello</span></div>'
|
const html = '<div><span>hello</span></div>'
|
||||||
const { vnode, container } = mountWithHydration(html, () =>
|
const { vnode, container } = mountWithHydration(html, () =>
|
||||||
|
@ -1177,5 +1187,21 @@ describe('SSR hydration', () => {
|
||||||
expect(teleportContainer.innerHTML).toBe(`<span>value</span>`)
|
expect(teleportContainer.innerHTML).toBe(`<span>value</span>`)
|
||||||
expect(`Hydration children mismatch`).toHaveBeenWarned()
|
expect(`Hydration children mismatch`).toHaveBeenWarned()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('comment mismatch (element)', () => {
|
||||||
|
const { container } = mountWithHydration(`<div><span></span></div>`, () =>
|
||||||
|
h('div', [createCommentVNode('hi')])
|
||||||
|
)
|
||||||
|
expect(container.innerHTML).toBe('<div><!--hi--></div>')
|
||||||
|
expect(`Hydration node mismatch`).toHaveBeenWarned()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('comment mismatch (text)', () => {
|
||||||
|
const { container } = mountWithHydration(`<div>foobar</div>`, () =>
|
||||||
|
h('div', [createCommentVNode('hi')])
|
||||||
|
)
|
||||||
|
expect(container.innerHTML).toBe('<div><!--hi--></div>')
|
||||||
|
expect(`Hydration node mismatch`).toHaveBeenWarned()
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -145,18 +145,17 @@ export function createHydrationFunctions(
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
case Comment:
|
case Comment:
|
||||||
if (domType !== DOMNodeTypes.COMMENT || isFragmentStart) {
|
if (isTemplateNode(node)) {
|
||||||
if ((node as Element).tagName.toLowerCase() === 'template') {
|
nextNode = nextSibling(node)
|
||||||
const content = (vnode.el! as HTMLTemplateElement).content
|
// wrapped <transition appear>
|
||||||
.firstChild!
|
// replace <template> node with inner child
|
||||||
|
replaceNode(
|
||||||
// replace <template> node with inner children
|
(vnode.el = node.content.firstChild!),
|
||||||
replaceNode(content, node, parentComponent)
|
node,
|
||||||
vnode.el = node = content
|
parentComponent
|
||||||
nextNode = nextSibling(node)
|
)
|
||||||
} else {
|
} else if (domType !== DOMNodeTypes.COMMENT || isFragmentStart) {
|
||||||
nextNode = onMismatch()
|
nextNode = onMismatch()
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
nextNode = nextSibling(node)
|
nextNode = nextSibling(node)
|
||||||
}
|
}
|
||||||
|
@ -209,7 +208,7 @@ export function createHydrationFunctions(
|
||||||
(domType !== DOMNodeTypes.ELEMENT ||
|
(domType !== DOMNodeTypes.ELEMENT ||
|
||||||
(vnode.type as string).toLowerCase() !==
|
(vnode.type as string).toLowerCase() !==
|
||||||
(node as Element).tagName.toLowerCase()) &&
|
(node as Element).tagName.toLowerCase()) &&
|
||||||
!isTemplateNode(node as Element)
|
!isTemplateNode(node)
|
||||||
) {
|
) {
|
||||||
nextNode = onMismatch()
|
nextNode = onMismatch()
|
||||||
} else {
|
} else {
|
||||||
|
@ -637,17 +636,16 @@ export function createHydrationFunctions(
|
||||||
let parent = parentComponent
|
let parent = parentComponent
|
||||||
while (parent) {
|
while (parent) {
|
||||||
if (parent.vnode.el === oldNode) {
|
if (parent.vnode.el === oldNode) {
|
||||||
parent.vnode.el = newNode
|
parent.vnode.el = parent.subTree.el = newNode
|
||||||
parent.subTree.el = newNode
|
|
||||||
}
|
}
|
||||||
parent = parent.parent
|
parent = parent.parent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const isTemplateNode = (node: Element): boolean => {
|
const isTemplateNode = (node: Node): node is HTMLTemplateElement => {
|
||||||
return (
|
return (
|
||||||
node.nodeType === DOMNodeTypes.ELEMENT &&
|
node.nodeType === DOMNodeTypes.ELEMENT &&
|
||||||
node.tagName.toLowerCase() === 'template'
|
(node as Element).tagName.toLowerCase() === 'template'
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue