fix(hydration): fix SFC style v-bind hydration mismatch warnings (#10250)

close #10215
This commit is contained in:
yangxiuxiu 2024-02-06 17:38:41 +08:00 committed by GitHub
parent f31d782e46
commit f0b5f7ed8d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 37 additions and 1 deletions

View File

@ -19,6 +19,7 @@ import {
onMounted,
ref,
renderSlot,
useCssVars,
vModelCheckbox,
vShow,
withDirectives,
@ -1538,5 +1539,20 @@ describe('SSR hydration', () => {
)
expect(`Hydration attribute mismatch`).not.toHaveBeenWarned()
})
test('should not warn css v-bind', () => {
const container = document.createElement('div')
container.innerHTML = `<div style="--foo:red;color:var(--foo);" />`
const app = createSSRApp({
setup() {
useCssVars(() => ({
foo: 'red',
}))
return () => h('div', { style: { color: 'var(--foo)' } })
},
})
app.mount(container)
expect(`Hydration style mismatch`).not.toHaveBeenWarned()
})
})
})

View File

@ -519,6 +519,12 @@ export interface ComponentInternalInstance {
* @internal
*/
ut?: (vars?: Record<string, string>) => void
/**
* dev only. For style v-bind hydration mismatch checks
* @internal
*/
getCssVars?: () => Record<string, string>
}
const emptyAppContext = createAppContext()

View File

@ -449,7 +449,10 @@ export function createHydrationFunctions(
) {
for (const key in props) {
// check hydration mismatch
if (__DEV__ && propHasMismatch(el, key, props[key], vnode)) {
if (
__DEV__ &&
propHasMismatch(el, key, props[key], vnode, parentComponent)
) {
hasMismatch = true
}
if (
@ -718,6 +721,7 @@ function propHasMismatch(
key: string,
clientValue: any,
vnode: VNode,
instance: ComponentInternalInstance | null,
): boolean {
let mismatchType: string | undefined
let mismatchKey: string | undefined
@ -748,6 +752,12 @@ function propHasMismatch(
}
}
}
const cssVars = instance?.getCssVars?.()
for (const key in cssVars) {
expectedMap.set(`--${key}`, String(cssVars[key]))
}
if (!isMapEqual(actualMap, expectedMap)) {
mismatchType = mismatchKey = 'style'
}

View File

@ -32,6 +32,10 @@ export function useCssVars(getter: (ctx: any) => Record<string, string>) {
).forEach(node => setVarsOnNode(node, vars))
})
if (__DEV__) {
instance.getCssVars = () => getter(instance.proxy)
}
const setVars = () => {
const vars = getter(instance.proxy)
setVarsOnVNode(instance.subTree, vars)