fix(v-show): v-show takes higher priority than style attribute (#3230)
fix #2757
This commit is contained in:
		
							parent
							
								
									45fae9d308
								
							
						
					
					
						commit
						5ad4036e29
					
				@ -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 value of `display` set by v-show should not be overwritten by the style attribute when updated', async () => {
 | 
			
		||||
    const style = ref('width: 100px')
 | 
			
		||||
    const display = ref(false)
 | 
			
		||||
    const component = defineComponent({
 | 
			
		||||
      render() {
 | 
			
		||||
        return withVShow(h('div', { style: style.value }), display.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')
 | 
			
		||||
 | 
			
		||||
    display.value = true
 | 
			
		||||
    await nextTick()
 | 
			
		||||
    expect($div.style.display).toEqual('')
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  // #2583, #2757
 | 
			
		||||
  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 display = ref(false)
 | 
			
		||||
    const component = defineComponent({
 | 
			
		||||
      setup() {
 | 
			
		||||
        const innerValue = ref(false)
 | 
			
		||||
        watch(display, val => {
 | 
			
		||||
          innerValue.value = val
 | 
			
		||||
        })
 | 
			
		||||
        return () => {
 | 
			
		||||
          return h(Transition, () =>
 | 
			
		||||
            withVShow(
 | 
			
		||||
              h('div', { style: style.value }, innerValue.value),
 | 
			
		||||
              display.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')
 | 
			
		||||
 | 
			
		||||
    display.value = true
 | 
			
		||||
    await nextTick()
 | 
			
		||||
    expect($div.style.display).toEqual('')
 | 
			
		||||
  })
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
@ -20,7 +20,8 @@ export const vShow: ObjectDirective<VShowElement> = {
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  updated(el, { value, oldValue }, { transition }) {
 | 
			
		||||
    if (transition && value !== oldValue) {
 | 
			
		||||
    if (!value === !oldValue) return
 | 
			
		||||
    if (transition) {
 | 
			
		||||
      if (value) {
 | 
			
		||||
        transition.beforeEnter(el)
 | 
			
		||||
        setDisplay(el, true)
 | 
			
		||||
 | 
			
		||||
@ -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 `display` 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) {
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user