]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(runtime-dom): fix nested v-show priority regression
authorEvan You <yyx990803@gmail.com>
Mon, 26 Feb 2024 01:11:05 +0000 (09:11 +0800)
committerEvan You <yyx990803@gmail.com>
Mon, 26 Feb 2024 01:11:05 +0000 (09:11 +0800)
close #10338

packages/runtime-dom/src/directives/vShow.ts
packages/runtime-dom/src/modules/style.ts

index 5bf48b277d9fce3dea90d1f42a44f1bfce069e88..9cf35bb9a9dd7c109c3b9168497c3ad4d4d0eff4 100644 (file)
@@ -1,10 +1,12 @@
 import type { ObjectDirective } from '@vue/runtime-core'
 
 export const vShowOriginalDisplay = Symbol('_vod')
+export const vShowHidden = Symbol('_vsh')
 
-interface VShowElement extends HTMLElement {
+export interface VShowElement extends HTMLElement {
   // _vod = vue original display
   [vShowOriginalDisplay]: string
+  [vShowHidden]: boolean
 }
 
 export const vShow: ObjectDirective<VShowElement> & { name?: 'show' } = {
@@ -23,11 +25,7 @@ export const vShow: ObjectDirective<VShowElement> & { name?: 'show' } = {
     }
   },
   updated(el, { value, oldValue }, { transition }) {
-    if (
-      !value === !oldValue &&
-      (el.style.display === el[vShowOriginalDisplay] || !value)
-    )
-      return
+    if (!value === !oldValue) return
     if (transition) {
       if (value) {
         transition.beforeEnter(el)
@@ -53,6 +51,7 @@ if (__DEV__) {
 
 function setDisplay(el: VShowElement, value: unknown): void {
   el.style.display = value ? el[vShowOriginalDisplay] : 'none'
+  el[vShowHidden] = !value
 }
 
 // SSR vnode transforms, only used when user includes client-oriented render
index 1f45966c3c4692e990c18a940417b42fec54f7e3..35d714ff085ee42b0d88f7d402f92a2b48e1cf9d 100644 (file)
@@ -1,6 +1,10 @@
 import { capitalize, hyphenate, isArray, isString } from '@vue/shared'
 import { camelize, warn } from '@vue/runtime-core'
-import { vShowOriginalDisplay } from '../directives/vShow'
+import {
+  type VShowElement,
+  vShowHidden,
+  vShowOriginalDisplay,
+} from '../directives/vShow'
 import { CSS_VAR_TEXT } from '../helpers/useCssVars'
 
 type Style = string | Record<string, string | string[]> | null
@@ -10,7 +14,6 @@ const displayRE = /(^|;)\s*display\s*:/
 export function patchStyle(el: Element, prev: Style, next: Style) {
   const style = (el as HTMLElement).style
   const isCssString = isString(next)
-  const currentDisplay = style.display
   let hasControlledDisplay = false
   if (next && !isCssString) {
     if (prev) {
@@ -50,12 +53,14 @@ export function patchStyle(el: Element, prev: Style, next: Style) {
       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`.
+  // indicates the element also has `v-show`.
   if (vShowOriginalDisplay in el) {
+    // make v-show respect the current v-bind style display when shown
     el[vShowOriginalDisplay] = hasControlledDisplay ? style.display : ''
-    style.display = currentDisplay
+    // if v-show is in hidden state, v-show has higher priority
+    if ((el as VShowElement)[vShowHidden]) {
+      style.display = 'none'
+    }
   }
 }