mirror of https://github.com/vuejs/core.git
fix(hydration): fix mismatch of leading newline in <textarea> and <pre>
close #11873 close #11874
This commit is contained in:
parent
3c4bf76276
commit
a5f3c2eb4d
|
@ -1908,6 +1908,21 @@ describe('SSR hydration', () => {
|
||||||
expect(`Hydration attribute mismatch`).toHaveBeenWarned()
|
expect(`Hydration attribute mismatch`).toHaveBeenWarned()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// #11873
|
||||||
|
test('<textarea> with newlines at the beginning', async () => {
|
||||||
|
const render = () => h('textarea', null, '\nhello')
|
||||||
|
const html = await renderToString(createSSRApp({ render }))
|
||||||
|
mountWithHydration(html, render)
|
||||||
|
expect(`Hydration text content mismatch`).not.toHaveBeenWarned()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('<pre> with newlines at the beginning', async () => {
|
||||||
|
const render = () => h('pre', null, '\n')
|
||||||
|
const html = await renderToString(createSSRApp({ render }))
|
||||||
|
mountWithHydration(html, render)
|
||||||
|
expect(`Hydration text content mismatch`).not.toHaveBeenWarned()
|
||||||
|
})
|
||||||
|
|
||||||
test('boolean attr handling', () => {
|
test('boolean attr handling', () => {
|
||||||
mountWithHydration(`<input />`, () => h('input', { readonly: false }))
|
mountWithHydration(`<input />`, () => h('input', { readonly: false }))
|
||||||
expect(`Hydration attribute mismatch`).not.toHaveBeenWarned()
|
expect(`Hydration attribute mismatch`).not.toHaveBeenWarned()
|
||||||
|
|
|
@ -440,7 +440,17 @@ export function createHydrationFunctions(
|
||||||
remove(cur)
|
remove(cur)
|
||||||
}
|
}
|
||||||
} else if (shapeFlag & ShapeFlags.TEXT_CHILDREN) {
|
} else if (shapeFlag & ShapeFlags.TEXT_CHILDREN) {
|
||||||
if (el.textContent !== vnode.children) {
|
// #11873 the HTML parser will "eat" the first newline when parsing
|
||||||
|
// <pre> and <textarea>, so if the client value starts with a newline,
|
||||||
|
// we need to remove it before comparing
|
||||||
|
let clientText = vnode.children as string
|
||||||
|
if (
|
||||||
|
clientText[0] === '\n' &&
|
||||||
|
(el.tagName === 'PRE' || el.tagName === 'TEXTAREA')
|
||||||
|
) {
|
||||||
|
clientText = clientText.slice(1)
|
||||||
|
}
|
||||||
|
if (el.textContent !== clientText) {
|
||||||
if (!isMismatchAllowed(el, MismatchTypes.TEXT)) {
|
if (!isMismatchAllowed(el, MismatchTypes.TEXT)) {
|
||||||
;(__DEV__ || __FEATURE_PROD_HYDRATION_MISMATCH_DETAILS__) &&
|
;(__DEV__ || __FEATURE_PROD_HYDRATION_MISMATCH_DETAILS__) &&
|
||||||
warn(
|
warn(
|
||||||
|
@ -753,7 +763,7 @@ export function createHydrationFunctions(
|
||||||
const isTemplateNode = (node: Node): node is HTMLTemplateElement => {
|
const isTemplateNode = (node: Node): node is HTMLTemplateElement => {
|
||||||
return (
|
return (
|
||||||
node.nodeType === DOMNodeTypes.ELEMENT &&
|
node.nodeType === DOMNodeTypes.ELEMENT &&
|
||||||
(node as Element).tagName.toLowerCase() === 'template'
|
(node as Element).tagName === 'TEMPLATE'
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue