Skip to content

Commit 07ece2e

Browse files
authored
fix(style-vars): fix css vars on component with suspense as root (#1718)
1 parent 58b4a38 commit 07ece2e

File tree

2 files changed

+57
-1
lines changed

2 files changed

+57
-1
lines changed

packages/runtime-dom/__tests__/helpers/useCssVars.spec.ts

+44-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ import {
44
h,
55
reactive,
66
nextTick,
7-
ComponentOptions
7+
ComponentOptions,
8+
Suspense
89
} from '@vue/runtime-dom'
910

1011
describe('useCssVars', () => {
@@ -68,6 +69,48 @@ describe('useCssVars', () => {
6869
}))
6970
})
7071

72+
test('on suspense root', async () => {
73+
const state = reactive({ color: 'red' })
74+
const root = document.createElement('div')
75+
76+
const AsyncComp = {
77+
async setup() {
78+
return () => h('p', 'default')
79+
}
80+
}
81+
82+
const App = {
83+
setup() {
84+
useCssVars(() => state)
85+
return () =>
86+
h(Suspense, null, {
87+
default: h(AsyncComp),
88+
fallback: h('div', 'fallback')
89+
})
90+
}
91+
}
92+
93+
render(h(App), root)
94+
// css vars use with fallback tree
95+
for (const c of [].slice.call(root.children as any)) {
96+
expect((c as HTMLElement).style.getPropertyValue(`--color`)).toBe(`red`)
97+
}
98+
// AsyncComp resolve
99+
await nextTick()
100+
// Suspense effects flush
101+
await nextTick()
102+
// css vars use with default tree
103+
for (const c of [].slice.call(root.children as any)) {
104+
expect((c as HTMLElement).style.getPropertyValue(`--color`)).toBe(`red`)
105+
}
106+
107+
state.color = 'green'
108+
await nextTick()
109+
for (const c of [].slice.call(root.children as any)) {
110+
expect((c as HTMLElement).style.getPropertyValue(`--color`)).toBe('green')
111+
}
112+
})
113+
71114
test('with <style scoped>', async () => {
72115
const id = 'data-v-12345'
73116

packages/runtime-dom/src/helpers/useCssVars.ts

+13
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,23 @@ function setVarsOnVNode(
3939
vars: Record<string, string>,
4040
prefix: string
4141
) {
42+
if (__FEATURE_SUSPENSE__ && vnode.shapeFlag & ShapeFlags.SUSPENSE) {
43+
const { isResolved, isHydrating, fallbackTree, subTree } = vnode.suspense!
44+
if (isResolved || isHydrating) {
45+
vnode = subTree
46+
} else {
47+
vnode.suspense!.effects.push(() => {
48+
setVarsOnVNode(subTree, vars, prefix)
49+
})
50+
vnode = fallbackTree
51+
}
52+
}
53+
4254
// drill down HOCs until it's a non-component vnode
4355
while (vnode.component) {
4456
vnode = vnode.component.subTree
4557
}
58+
4659
if (vnode.shapeFlag & ShapeFlags.ELEMENT && vnode.el) {
4760
const style = vnode.el.style
4861
for (const key in vars) {

0 commit comments

Comments
 (0)