From 7ab46ff9dbd6ee3e5e89518e7cd16b3e944886ae Mon Sep 17 00:00:00 2001 From: HcySunYang Date: Sun, 14 Feb 2021 23:21:51 +0800 Subject: [PATCH 1/3] fix(v-show): v-show has a higher priority than the style attribute --- .../__tests__/directives/vShow.spec.ts | 65 ++++++++++++++++++- packages/runtime-dom/src/directives/vShow.ts | 21 +++--- packages/runtime-dom/src/modules/style.ts | 7 ++ 3 files changed, 82 insertions(+), 11 deletions(-) diff --git a/packages/runtime-dom/__tests__/directives/vShow.spec.ts b/packages/runtime-dom/__tests__/directives/vShow.spec.ts index 6c21e5f83f0..ed8f982f9d3 100644 --- a/packages/runtime-dom/__tests__/directives/vShow.spec.ts +++ b/packages/runtime-dom/__tests__/directives/vShow.spec.ts @@ -3,9 +3,11 @@ import { defineComponent, h, nextTick, - VNode + VNode, + ref, + watch } from '@vue/runtime-core' -import { render, vShow } from '@vue/runtime-dom' +import { render, Transition, vShow } from '@vue/runtime-dom' const withVShow = (node: VNode, exp: any) => withDirectives(node, [[vShow, exp]]) @@ -124,4 +126,63 @@ describe('runtime-dom: v-show directive', () => { await nextTick() expect($div.style.display).toEqual('block') }) + + // #2583 + test('the dispaly attr set by v-show should not be overwritten by the style attribute when updated', async () => { + const style = ref('width: 100px') + const dispaly = ref(false) + const component = defineComponent({ + render() { + return withVShow(h('div', { style: style.value }), dispaly.value) + } + }) + render(h(component), root) + + const $div = root.querySelector('div') + + expect($div.style.display).toEqual('none') + + style.value = 'width: 50px' + await nextTick() + expect($div.style.display).toEqual('none') + + dispaly.value = true + await nextTick() + expect($div.style.display).toEqual('') + }) + + // #2583, #2757 + test('the dispaly attr set by v-show should not be overwritten by the style attribute when updated (with Transition)', async () => { + const style = ref('width: 100px') + const dispaly = ref(false) + const component = defineComponent({ + setup() { + const innerValue = ref(false) + watch(dispaly, val => { + innerValue.value = val + }) + return () => { + return h(Transition, () => + withVShow( + h('div', { style: style.value }, innerValue.value), + dispaly.value + ) + ) + } + } + }) + render(h(component), root) + + const $div = root.querySelector('div') + + expect($div.style.display).toEqual('none') + + style.value = 'width: 50px' + await nextTick() + expect($div.style.display).toEqual('none') + + dispaly.value = true + await nextTick() + expect($div.style.display).toEqual('') + }) }) diff --git a/packages/runtime-dom/src/directives/vShow.ts b/packages/runtime-dom/src/directives/vShow.ts index f94ac3bae3b..52a2542e204 100644 --- a/packages/runtime-dom/src/directives/vShow.ts +++ b/packages/runtime-dom/src/directives/vShow.ts @@ -20,15 +20,18 @@ export const vShow: ObjectDirective = { } }, updated(el, { value, oldValue }, { transition }) { - if (transition && value !== oldValue) { - if (value) { - transition.beforeEnter(el) - setDisplay(el, true) - transition.enter(el) - } else { - transition.leave(el, () => { - setDisplay(el, false) - }) + if (!value === !oldValue) return + if (transition) { + if (value !== oldValue) { + if (value) { + transition.beforeEnter(el) + setDisplay(el, true) + transition.enter(el) + } else { + transition.leave(el, () => { + setDisplay(el, false) + }) + } } } else { setDisplay(el, value) diff --git a/packages/runtime-dom/src/modules/style.ts b/packages/runtime-dom/src/modules/style.ts index 30816b58d83..c9473844fe7 100644 --- a/packages/runtime-dom/src/modules/style.ts +++ b/packages/runtime-dom/src/modules/style.ts @@ -9,7 +9,14 @@ export function patchStyle(el: Element, prev: Style, next: Style) { el.removeAttribute('style') } else if (isString(next)) { if (prev !== next) { + const current = style.display style.cssText = next + // indicates that the `display` of the element is controlled by `v-show`, + // so we always keep the current `dispaly` value regardless of the `style` value, + // thus handing over control to `v-show`. + if ('_vod' in el) { + style.display = current + } } } else { for (const key in next) { From d3defa2018c41dcd916a9051a4cb2ec575ce8b90 Mon Sep 17 00:00:00 2001 From: HcySunYang Date: Mon, 15 Feb 2021 10:49:51 +0800 Subject: [PATCH 2/3] chore: tweak the words --- packages/runtime-dom/__tests__/directives/vShow.spec.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/runtime-dom/__tests__/directives/vShow.spec.ts b/packages/runtime-dom/__tests__/directives/vShow.spec.ts index ed8f982f9d3..48419fc0a67 100644 --- a/packages/runtime-dom/__tests__/directives/vShow.spec.ts +++ b/packages/runtime-dom/__tests__/directives/vShow.spec.ts @@ -128,7 +128,7 @@ describe('runtime-dom: v-show directive', () => { }) // #2583 - test('the dispaly attr set by v-show should not be overwritten by the style attribute when updated', async () => { + test('the value of `dispaly` set by v-show should not be overwritten by the style attribute when updated', async () => { const style = ref('width: 100px') const dispaly = ref(false) const component = defineComponent({ @@ -152,7 +152,7 @@ describe('runtime-dom: v-show directive', () => { }) // #2583, #2757 - test('the dispaly attr set by v-show should not be overwritten by the style attribute when updated (with Transition)', async () => { + test('the value of `dispaly` set by v-show should not be overwritten by the style attribute when updated (with Transition)', async () => { const style = ref('width: 100px') const dispaly = ref(false) const component = defineComponent({ From 02da60b3ee341b3db800c1c24491496ea7232d2d Mon Sep 17 00:00:00 2001 From: HcySunYang Date: Wed, 17 Feb 2021 10:30:27 +0800 Subject: [PATCH 3/3] fix: remove unnecessary if branche + fix spelling --- .../__tests__/directives/vShow.spec.ts | 18 +++++++++--------- packages/runtime-dom/src/directives/vShow.ts | 18 ++++++++---------- packages/runtime-dom/src/modules/style.ts | 2 +- 3 files changed, 18 insertions(+), 20 deletions(-) diff --git a/packages/runtime-dom/__tests__/directives/vShow.spec.ts b/packages/runtime-dom/__tests__/directives/vShow.spec.ts index 48419fc0a67..545e22b9c75 100644 --- a/packages/runtime-dom/__tests__/directives/vShow.spec.ts +++ b/packages/runtime-dom/__tests__/directives/vShow.spec.ts @@ -128,12 +128,12 @@ describe('runtime-dom: v-show directive', () => { }) // #2583 - test('the value of `dispaly` set by v-show should not be overwritten by the style attribute when updated', async () => { + test('the value of `display` set by v-show should not be overwritten by the style attribute when updated', async () => { const style = ref('width: 100px') - const dispaly = ref(false) + const display = ref(false) const component = defineComponent({ render() { - return withVShow(h('div', { style: style.value }), dispaly.value) + return withVShow(h('div', { style: style.value }), display.value) } }) render(h(component), root) @@ -146,26 +146,26 @@ describe('runtime-dom: v-show directive', () => { await nextTick() expect($div.style.display).toEqual('none') - dispaly.value = true + display.value = true await nextTick() expect($div.style.display).toEqual('') }) // #2583, #2757 - test('the value of `dispaly` set by v-show should not be overwritten by the style attribute when updated (with Transition)', async () => { + test('the value of `display` set by v-show should not be overwritten by the style attribute when updated (with Transition)', async () => { const style = ref('width: 100px') - const dispaly = ref(false) + const display = ref(false) const component = defineComponent({ setup() { const innerValue = ref(false) - watch(dispaly, val => { + watch(display, val => { innerValue.value = val }) return () => { return h(Transition, () => withVShow( h('div', { style: style.value }, innerValue.value), - dispaly.value + display.value ) ) } @@ -181,7 +181,7 @@ describe('runtime-dom: v-show directive', () => { await nextTick() expect($div.style.display).toEqual('none') - dispaly.value = true + display.value = true await nextTick() expect($div.style.display).toEqual('') }) diff --git a/packages/runtime-dom/src/directives/vShow.ts b/packages/runtime-dom/src/directives/vShow.ts index 52a2542e204..d9bf3af5487 100644 --- a/packages/runtime-dom/src/directives/vShow.ts +++ b/packages/runtime-dom/src/directives/vShow.ts @@ -22,16 +22,14 @@ export const vShow: ObjectDirective = { updated(el, { value, oldValue }, { transition }) { if (!value === !oldValue) return if (transition) { - if (value !== oldValue) { - if (value) { - transition.beforeEnter(el) - setDisplay(el, true) - transition.enter(el) - } else { - transition.leave(el, () => { - setDisplay(el, false) - }) - } + if (value) { + transition.beforeEnter(el) + setDisplay(el, true) + transition.enter(el) + } else { + transition.leave(el, () => { + setDisplay(el, false) + }) } } else { setDisplay(el, value) diff --git a/packages/runtime-dom/src/modules/style.ts b/packages/runtime-dom/src/modules/style.ts index c9473844fe7..1084e5b2f8f 100644 --- a/packages/runtime-dom/src/modules/style.ts +++ b/packages/runtime-dom/src/modules/style.ts @@ -12,7 +12,7 @@ export function patchStyle(el: Element, prev: Style, next: Style) { const current = style.display style.cssText = next // indicates that the `display` of the element is controlled by `v-show`, - // so we always keep the current `dispaly` value regardless of the `style` value, + // 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 = current