From 6a0c7cd9051e1b3eb1a3ce1eaadfd9c828b53daa Mon Sep 17 00:00:00 2001 From: edison Date: Thu, 15 Jul 2021 06:08:12 +0800 Subject: [PATCH] fix(sfc): fix style variables injection on static vnode (#3847) fix #3841 --- .../__tests__/helpers/useCssVars.spec.ts | 23 +++++++++++++++++++ .../runtime-dom/src/helpers/useCssVars.ts | 20 +++++++++++++--- 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/packages/runtime-dom/__tests__/helpers/useCssVars.spec.ts b/packages/runtime-dom/__tests__/helpers/useCssVars.spec.ts index ae86e57b..a72d0a9c 100644 --- a/packages/runtime-dom/__tests__/helpers/useCssVars.spec.ts +++ b/packages/runtime-dom/__tests__/helpers/useCssVars.spec.ts @@ -2,6 +2,7 @@ import { ref, render, useCssVars, + createStaticVNode, h, reactive, nextTick, @@ -140,4 +141,26 @@ describe('useCssVars', () => { expect((c as HTMLElement).style.getPropertyValue(`--color`)).toBe('red') } }) + + test('with createStaticVNode', async () => { + const state = reactive({ color: 'red' }) + const root = document.createElement('div') + + const App = { + setup() { + useCssVars(() => state) + return () => [ + h('div'), + createStaticVNode('
1
2
', 2), + h('div') + ] + } + } + + render(h(App), root) + await nextTick() + for (const c of [].slice.call(root.children as any)) { + expect((c as HTMLElement).style.getPropertyValue(`--color`)).toBe('red') + } + }) }) diff --git a/packages/runtime-dom/src/helpers/useCssVars.ts b/packages/runtime-dom/src/helpers/useCssVars.ts index 82c48e33..3253dd22 100644 --- a/packages/runtime-dom/src/helpers/useCssVars.ts +++ b/packages/runtime-dom/src/helpers/useCssVars.ts @@ -4,6 +4,7 @@ import { warn, VNode, Fragment, + Static, onUpdated, watchEffect } from '@vue/runtime-core' @@ -47,11 +48,24 @@ function setVarsOnVNode(vnode: VNode, vars: Record) { } if (vnode.shapeFlag & ShapeFlags.ELEMENT && vnode.el) { - const style = vnode.el.style + setVarsOnNode(vnode.el as Node, vars) + } else if (vnode.type === Fragment) { + ;(vnode.children as VNode[]).forEach(c => setVarsOnVNode(c, vars)) + } else if (vnode.type === Static) { + let { el, anchor } = vnode + while (el) { + setVarsOnNode(el as Node, vars) + if (el === anchor) break + el = el.nextSibling + } + } +} + +function setVarsOnNode(el: Node, vars: Record) { + if (el.nodeType === 1) { + const style = (el as HTMLElement).style for (const key in vars) { style.setProperty(`--${key}`, vars[key]) } - } else if (vnode.type === Fragment) { - ;(vnode.children as VNode[]).forEach(c => setVarsOnVNode(c, vars)) } }