]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(runtime-dom): fix behavior regression for v-show + style display binding
authorEvan You <yyx990803@gmail.com>
Sat, 9 Oct 2021 23:31:52 +0000 (19:31 -0400)
committerEvan You <yyx990803@gmail.com>
Sat, 9 Oct 2021 23:31:52 +0000 (19:31 -0400)
fix #4768

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

index b8dfc49d590d1adc0ecdae502ab50854730cb60e..92b30aa5815bf8fb7451b41ea2ee64721b2ec455 100644 (file)
@@ -68,6 +68,14 @@ describe(`runtime-dom: style patching`, () => {
     expect(el.style.width).toBe('0px')
   })
 
+  it('should remove style attribute on falsy value', () => {
+    const el = document.createElement('div')
+    el.style.cssText = 'color: red;'
+    patchProp(el as any, 'style', {}, null)
+    expect(el.hasAttribute('style')).toBe(false)
+    expect(el.style.cssText).toBe('')
+  })
+
   // JSDOM doesn't support custom properties on style object so we have to
   // mock it here.
   function mockElementWithStyle() {
index 69a608795d972754a78b1b97b8befb65b438725e..a9cc67ba5e2520d86f3a668ebe3ce5e0869963a6 100644 (file)
@@ -5,14 +5,8 @@ type Style = string | Record<string, string | string[]> | null
 
 export function patchStyle(el: Element, prev: Style, next: Style) {
   const style = (el as HTMLElement).style
-  const currentDisplay = style.display
-  if (!next) {
-    el.removeAttribute('style')
-  } else if (isString(next)) {
-    if (prev !== next) {
-      style.cssText = next
-    }
-  } else {
+  const isCssString = isString(next)
+  if (next && !isCssString) {
     for (const key in next) {
       setStyle(style, key, next[key])
     }
@@ -23,12 +17,21 @@ export function patchStyle(el: Element, prev: Style, next: Style) {
         }
       }
     }
-  }
-  // indicates that the `display` of the element is controlled by `v-show`,
-  // so we always keep the current `display` value regardless of the `style` value,
-  // thus handing over control to `v-show`.
-  if ('_vod' in el) {
-    style.display = currentDisplay
+  } else {
+    const currentDisplay = style.display
+    if (isCssString) {
+      if (prev !== next) {
+        style.cssText = next as string
+      }
+    } else if (prev) {
+      el.removeAttribute('style')
+    }
+    // indicates that the `display` of the element is controlled by `v-show`,
+    // so we always keep the current `display` value regardless of the `style`
+    // value, thus handing over control to `v-show`.
+    if ('_vod' in el) {
+      style.display = currentDisplay
+    }
   }
 }