mirror of https://github.com/vuejs/core.git
fix(hydration): fix css vars hydration mismatch false positive on attr-fallthrough (#11190)
close #11188
This commit is contained in:
parent
80ba50d74c
commit
7ad67ced26
|
@ -1674,5 +1674,26 @@ describe('SSR hydration', () => {
|
||||||
app.mount(container)
|
app.mount(container)
|
||||||
expect(`Hydration style mismatch`).not.toHaveBeenWarned()
|
expect(`Hydration style mismatch`).not.toHaveBeenWarned()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// #11188
|
||||||
|
test('css vars support fallthrough', () => {
|
||||||
|
const container = document.createElement('div')
|
||||||
|
container.innerHTML = `<div style="padding: 4px;--foo:red;"></div>`
|
||||||
|
const app = createSSRApp({
|
||||||
|
setup() {
|
||||||
|
useCssVars(() => ({
|
||||||
|
foo: 'red',
|
||||||
|
}))
|
||||||
|
return () => h(Child)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
const Child = {
|
||||||
|
setup() {
|
||||||
|
return () => h('div', { style: 'padding: 4px' })
|
||||||
|
},
|
||||||
|
}
|
||||||
|
app.mount(container)
|
||||||
|
expect(`Hydration style mismatch`).not.toHaveBeenWarned()
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -766,18 +766,8 @@ function propHasMismatch(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line no-restricted-syntax
|
if (instance) {
|
||||||
const root = instance?.subTree
|
resolveCssVars(instance, vnode, expectedMap)
|
||||||
if (
|
|
||||||
vnode === root ||
|
|
||||||
// eslint-disable-next-line no-restricted-syntax
|
|
||||||
(root?.type === Fragment && (root.children as VNode[]).includes(vnode))
|
|
||||||
) {
|
|
||||||
// eslint-disable-next-line no-restricted-syntax
|
|
||||||
const cssVars = instance?.getCssVars?.()
|
|
||||||
for (const key in cssVars) {
|
|
||||||
expectedMap.set(`--${key}`, String(cssVars[key]))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isMapEqual(actualMap, expectedMap)) {
|
if (!isMapEqual(actualMap, expectedMap)) {
|
||||||
|
@ -854,10 +844,8 @@ function toStyleMap(str: string): Map<string, string> {
|
||||||
const styleMap: Map<string, string> = new Map()
|
const styleMap: Map<string, string> = new Map()
|
||||||
for (const item of str.split(';')) {
|
for (const item of str.split(';')) {
|
||||||
let [key, value] = item.split(':')
|
let [key, value] = item.split(':')
|
||||||
// eslint-disable-next-line no-restricted-syntax
|
key = key.trim()
|
||||||
key = key?.trim()
|
value = value && value.trim()
|
||||||
// eslint-disable-next-line no-restricted-syntax
|
|
||||||
value = value?.trim()
|
|
||||||
if (key && value) {
|
if (key && value) {
|
||||||
styleMap.set(key, value)
|
styleMap.set(key, value)
|
||||||
}
|
}
|
||||||
|
@ -876,3 +864,26 @@ function isMapEqual(a: Map<string, string>, b: Map<string, string>): boolean {
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function resolveCssVars(
|
||||||
|
instance: ComponentInternalInstance,
|
||||||
|
vnode: VNode,
|
||||||
|
expectedMap: Map<string, string>,
|
||||||
|
) {
|
||||||
|
const root = instance.subTree
|
||||||
|
if (
|
||||||
|
instance.getCssVars &&
|
||||||
|
(vnode === root ||
|
||||||
|
(root &&
|
||||||
|
root.type === Fragment &&
|
||||||
|
(root.children as VNode[]).includes(vnode)))
|
||||||
|
) {
|
||||||
|
const cssVars = instance.getCssVars()
|
||||||
|
for (const key in cssVars) {
|
||||||
|
expectedMap.set(`--${key}`, String(cssVars[key]))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (vnode === root && instance.parent) {
|
||||||
|
resolveCssVars(instance.parent, instance.vnode, expectedMap)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue