]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(sfc/cssVars): fix loss of CSS v-bind variables when setting inline style with...
author丶远方 <yangpanteng@gmail.com>
Fri, 15 Dec 2023 01:56:01 +0000 (09:56 +0800)
committerGitHub <noreply@github.com>
Fri, 15 Dec 2023 01:56:01 +0000 (09:56 +0800)
close #9821

packages/runtime-dom/__tests__/helpers/useCssVars.spec.ts
packages/runtime-dom/src/helpers/useCssVars.ts
packages/runtime-dom/src/modules/style.ts

index 5792a0107b137a48118de062ca18562ac6809a91..0d8b8d0d26e90d51396833e403162210b90b490e 100644 (file)
@@ -293,4 +293,35 @@ describe('useCssVars', () => {
     await nextTick()
     expect(target.children.length).toBe(0)
   })
+
+  test('with string style', async () => {
+    document.body.innerHTML = ''
+    const state = reactive({ color: 'red' })
+    const root = document.createElement('div')
+    const disabled = ref(false)
+
+    const App = {
+      setup() {
+        useCssVars(() => state)
+        return () => [
+          h(
+            'div',
+            { style: disabled.value ? 'pointer-events: none' : undefined },
+            'foo'
+          )
+        ]
+      }
+    }
+    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')
+    }
+    disabled.value = true
+    await nextTick()
+
+    for (const c of [].slice.call(root.children as any)) {
+      expect((c as HTMLElement).style.getPropertyValue(`--color`)).toBe('red')
+    }
+  })
 })
index e0a95c9ca997c08e9f2dac5848889ddf78b5c7db..4bd9838ba75f47e9cd2c633788c3d07bd1825323 100644 (file)
@@ -10,6 +10,7 @@ import {
 } from '@vue/runtime-core'
 import { ShapeFlags } from '@vue/shared'
 
+export const CSS_VAR_TEXT = Symbol(__DEV__ ? 'CSS_VAR_TEXT' : '')
 /**
  * Runtime helper for SFC's CSS variable injection feature.
  * @private
@@ -79,8 +80,11 @@ function setVarsOnVNode(vnode: VNode, vars: Record<string, string>) {
 function setVarsOnNode(el: Node, vars: Record<string, string>) {
   if (el.nodeType === 1) {
     const style = (el as HTMLElement).style
+    let cssText = ''
     for (const key in vars) {
       style.setProperty(`--${key}`, vars[key])
+      cssText += `--${key}: ${vars[key]};`
     }
+    ;(style as any)[CSS_VAR_TEXT] = cssText
   }
 }
index c18fd8aa9d50ce43d3672cb80ad601bfc44494c2..cb4ee7772512fff94f6e8ccae583f7ecb1998b8a 100644 (file)
@@ -1,6 +1,7 @@
 import { isString, hyphenate, capitalize, isArray } from '@vue/shared'
 import { camelize, warn } from '@vue/runtime-core'
 import { vShowOldKey } from '../directives/vShow'
+import { CSS_VAR_TEXT } from '../helpers/useCssVars'
 
 type Style = string | Record<string, string | string[]> | null
 
@@ -22,6 +23,11 @@ export function patchStyle(el: Element, prev: Style, next: Style) {
     const currentDisplay = style.display
     if (isCssString) {
       if (prev !== next) {
+        // #9821
+        const cssVarText = (style as any)[CSS_VAR_TEXT]
+        if (cssVarText) {
+          ;(next as string) += ';' + cssVarText
+        }
         style.cssText = next as string
       }
     } else if (prev) {