Browse Source

fix transition enter hook for v-show (fix #3433)

dev
Evan You 8 years ago
parent
commit
299f529498
  1. 24
      src/platforms/web/runtime/modules/transition.js
  2. 73
      test/unit/features/transition/transition.spec.js

24
src/platforms/web/runtime/modules/transition.js

@ -92,15 +92,17 @@ export function enter (vnode: VNodeWithData) {
el._enterCb = null
})
// remove pending leave element on enter by injecting an insert hook
mergeVNodeHook(vnode.data.hook || (vnode.data.hook = {}), 'insert', () => {
const parent = el.parentNode
const pendingNode = parent._pending && parent._pending[vnode.key]
if (pendingNode && pendingNode.tag === vnode.tag && pendingNode.elm._leaveCb) {
pendingNode.elm._leaveCb()
}
enterHook && enterHook(el, cb)
})
if (!vnode.data.show) {
// remove pending leave element on enter by injecting an insert hook
mergeVNodeHook(vnode.data.hook || (vnode.data.hook = {}), 'insert', () => {
const parent = el.parentNode
const pendingNode = parent._pending && parent._pending[vnode.key]
if (pendingNode && pendingNode.tag === vnode.tag && pendingNode.elm._leaveCb) {
pendingNode.elm._leaveCb()
}
enterHook && enterHook(el, cb)
})
}
// start enter transition
beforeEnterHook && beforeEnterHook(el)
@ -115,6 +117,10 @@ export function enter (vnode: VNodeWithData) {
})
}
if (vnode.data.show) {
enterHook && enterHook(el, cb)
}
if (!expectsCSS && !userWantsControl) {
cb()
}

73
test/unit/features/transition/transition.spec.js

@ -253,6 +253,79 @@ if (!isIE9) {
}).then(done)
})
fit('transition events (v-show)', done => {
const onLeaveSpy = jasmine.createSpy('leave')
const onEnterSpy = jasmine.createSpy('enter')
const beforeLeaveSpy = jasmine.createSpy('beforeLeave')
const beforeEnterSpy = jasmine.createSpy('beforeEnter')
const afterLeaveSpy = jasmine.createSpy('afterLeave')
const afterEnterSpy = jasmine.createSpy('afterEnter')
const vm = new Vue({
template: `
<div>
<transition
name="test"
@before-enter="beforeEnter"
@enter="enter"
@after-enter="afterEnter"
@before-leave="beforeLeave"
@leave="leave"
@after-leave="afterLeave">
<div v-show="ok" class="test">foo</div>
</transition>
</div>
`,
data: { ok: true },
methods: {
beforeLeave: (el) => {
expect(el).toBe(vm.$el.children[0])
expect(el.className).toBe('test')
beforeLeaveSpy(el)
},
leave: (el) => onLeaveSpy(el),
afterLeave: (el) => afterLeaveSpy(el),
beforeEnter: (el) => {
expect(el.className).toBe('test')
beforeEnterSpy(el)
},
enter: (el) => {
onEnterSpy(el)
},
afterEnter: (el) => afterEnterSpy(el)
}
}).$mount(el)
// should not apply transition on initial render by default
expect(vm.$el.innerHTML).toBe('<div class="test">foo</div>')
let _el = vm.$el.children[0]
vm.ok = false
waitForUpdate(() => {
expect(beforeLeaveSpy).toHaveBeenCalledWith(_el)
expect(onLeaveSpy).toHaveBeenCalledWith(_el)
expect(vm.$el.children[0].className).toBe('test test-leave test-leave-active')
}).thenWaitFor(nextFrame).then(() => {
expect(afterLeaveSpy).not.toHaveBeenCalled()
expect(vm.$el.children[0].className).toBe('test test-leave-active')
}).thenWaitFor(duration + 10).then(() => {
expect(afterLeaveSpy).toHaveBeenCalledWith(_el)
expect(vm.$el.children[0].style.display).toBe('none')
vm.ok = true
}).then(() => {
_el = vm.$el.children[0]
expect(beforeEnterSpy).toHaveBeenCalledWith(_el)
expect(onEnterSpy).toHaveBeenCalledWith(_el)
expect(vm.$el.children[0].className).toBe('test test-enter test-enter-active')
}).thenWaitFor(nextFrame).then(() => {
expect(afterEnterSpy).not.toHaveBeenCalled()
expect(vm.$el.children[0].className).toBe('test test-enter-active')
}).thenWaitFor(duration + 10).then(() => {
expect(afterEnterSpy).toHaveBeenCalledWith(_el)
expect(vm.$el.children[0].className).toBe('test')
}).then(done)
})
it('explicit user callback in JavaScript hooks', done => {
let next
const vm = new Vue({

Loading…
Cancel
Save