From: yangxiuxiu <79584569+yangxiuxiu1115@users.noreply.github.com> Date: Tue, 6 Feb 2024 09:38:41 +0000 (+0800) Subject: fix(hydration): fix SFC style v-bind hydration mismatch warnings (#10250) X-Git-Tag: v3.4.16~10 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f0b5f7ed8ddf74f9f5ba47cb65e8300370875291;p=thirdparty%2Fvuejs%2Fcore.git fix(hydration): fix SFC style v-bind hydration mismatch warnings (#10250) close #10215 --- diff --git a/packages/runtime-core/__tests__/hydration.spec.ts b/packages/runtime-core/__tests__/hydration.spec.ts index 127c0d88c7..3fa0d7e732 100644 --- a/packages/runtime-core/__tests__/hydration.spec.ts +++ b/packages/runtime-core/__tests__/hydration.spec.ts @@ -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 = `
` + const app = createSSRApp({ + setup() { + useCssVars(() => ({ + foo: 'red', + })) + return () => h('div', { style: { color: 'var(--foo)' } }) + }, + }) + app.mount(container) + expect(`Hydration style mismatch`).not.toHaveBeenWarned() + }) }) }) diff --git a/packages/runtime-core/src/component.ts b/packages/runtime-core/src/component.ts index 1508627e57..ed1f8efee5 100644 --- a/packages/runtime-core/src/component.ts +++ b/packages/runtime-core/src/component.ts @@ -519,6 +519,12 @@ export interface ComponentInternalInstance { * @internal */ ut?: (vars?: Record) => void + + /** + * dev only. For style v-bind hydration mismatch checks + * @internal + */ + getCssVars?: () => Record } const emptyAppContext = createAppContext() diff --git a/packages/runtime-core/src/hydration.ts b/packages/runtime-core/src/hydration.ts index b22afdb7aa..1e9200ce27 100644 --- a/packages/runtime-core/src/hydration.ts +++ b/packages/runtime-core/src/hydration.ts @@ -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' } diff --git a/packages/runtime-dom/src/helpers/useCssVars.ts b/packages/runtime-dom/src/helpers/useCssVars.ts index 72714e6f62..1666e3cb3d 100644 --- a/packages/runtime-dom/src/helpers/useCssVars.ts +++ b/packages/runtime-dom/src/helpers/useCssVars.ts @@ -32,6 +32,10 @@ export function useCssVars(getter: (ctx: any) => Record) { ).forEach(node => setVarsOnNode(node, vars)) }) + if (__DEV__) { + instance.getCssVars = () => getter(instance.proxy) + } + const setVars = () => { const vars = getter(instance.proxy) setVarsOnVNode(instance.subTree, vars)