Skip to content

Commit

Permalink
fix(runtime-dom): set css vars on update to handle child forcing refl…
Browse files Browse the repository at this point in the history
…ow in onMount (vuejs#11561)
  • Loading branch information
linzhe141 authored Nov 14, 2024
1 parent 2d5c5e2 commit c4312f9
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 0 deletions.
38 changes: 38 additions & 0 deletions packages/runtime-dom/__tests__/helpers/useCssVars.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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' })
Expand Down
8 changes: 8 additions & 0 deletions packages/runtime-dom/src/helpers/useCssVars.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ import {
Static,
type VNode,
getCurrentInstance,
onBeforeUpdate,
onMounted,
onUnmounted,
queuePostFlushCb,
warn,
watch,
} from '@vue/runtime-core'
Expand Down Expand Up @@ -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' })
Expand Down

0 comments on commit c4312f9

Please sign in to comment.