]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(runtime-dom): set css vars on update to handle child forcing reflow in onMount...
authorlinzhe <40790268+linzhe141@users.noreply.github.com>
Thu, 14 Nov 2024 07:58:28 +0000 (15:58 +0800)
committerGitHub <noreply@github.com>
Thu, 14 Nov 2024 07:58:28 +0000 (15:58 +0800)
packages/runtime-dom/__tests__/helpers/useCssVars.spec.ts
packages/runtime-dom/src/helpers/useCssVars.ts

index acba3315862a4d480c109cc5ea615935167ca46c..1fb4cc65fd0cafa8a2577c04a084179592ac00ab 100644 (file)
@@ -385,6 +385,44 @@ describe('useCssVars', () => {
     }
   })
 
+  test('with delay mount child', async () => {
+    const state = reactive({ color: 'red' })
+    const value = ref(false)
+    const root = document.createElement('div')
+
+    const Child = {
+      setup() {
+        onMounted(() => {
+          const childEl = root.children[0]
+          expect(getComputedStyle(childEl!).getPropertyValue(`--color`)).toBe(
+            `red`,
+          )
+        })
+        return () => h('div', { id: 'childId' })
+      },
+    }
+    const App = {
+      setup() {
+        useCssVars(() => state)
+        return () => (value.value ? h(Child) : [h('span')])
+      },
+    }
+
+    render(h(App), root)
+    await nextTick()
+    // css vars use with fallback tree
+    for (const c of [].slice.call(root.children as any)) {
+      expect((c as HTMLElement).style.getPropertyValue(`--color`)).toBe(`red`)
+    }
+
+    // mount child
+    value.value = true
+    await nextTick()
+    for (const c of [].slice.call(root.children as any)) {
+      expect((c as HTMLElement).style.getPropertyValue(`--color`)).toBe(`red`)
+    }
+  })
+
   // #8826
   test('with custom element', async () => {
     const state = reactive({ color: 'red' })
index 6331208c5c0e5dea22d7328d3464fc692fc5b026..e2bc6de92781cd046ef087e9ced48d3633be2bbc 100644 (file)
@@ -3,8 +3,10 @@ import {
   Static,
   type VNode,
   getCurrentInstance,
+  onBeforeUpdate,
   onMounted,
   onUnmounted,
+  queuePostFlushCb,
   warn,
   watch,
 } from '@vue/runtime-core'
@@ -47,6 +49,12 @@ export function useCssVars(getter: (ctx: any) => Record<string, string>): void {
     updateTeleports(vars)
   }
 
+  // handle cases where child component root is affected
+  // and triggers reflow in onMounted
+  onBeforeUpdate(() => {
+    queuePostFlushCb(setVars)
+  })
+
   onMounted(() => {
     // run setVars synchronously here, but run as post-effect on changes
     watch(setVars, NOOP, { flush: 'post' })