Skip to content

Commit 6e471ea

Browse files
committed
fix v-show transition on child component root (fix #3354)
1 parent 45e1ffd commit 6e471ea

File tree

2 files changed

+85
-2
lines changed

2 files changed

+85
-2
lines changed

src/platforms/web/runtime/directives/show.js

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,25 @@
33
import { isIE9 } from 'web/util/index'
44
import { enter, leave } from '../modules/transition'
55

6+
// recursively search for possible transition defined inside the component root
7+
function locateNode (vnode: VNode): VNodeWithData {
8+
return vnode.child && (!vnode.data || !vnode.data.transition)
9+
? locateNode(vnode.child._vnode)
10+
: vnode
11+
}
12+
613
export default {
714
bind (el: HTMLElement, { value }: VNodeDirective, vnode: VNodeWithData) {
8-
const transition = vnode.data.transition
15+
vnode = locateNode(vnode)
16+
const transition = vnode.data && vnode.data.transition
917
if (value && transition && transition.appear && !isIE9) {
1018
enter(vnode)
1119
}
1220
el.style.display = value ? '' : 'none'
1321
},
1422
update (el: HTMLElement, { value }: VNodeDirective, vnode: VNodeWithData) {
15-
const transition = vnode.data.transition
23+
vnode = locateNode(vnode)
24+
const transition = vnode.data && vnode.data.transition
1625
if (transition && !isIE9) {
1726
if (value) {
1827
enter(vnode)

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

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -449,6 +449,42 @@ if (!isIE9) {
449449
}).then(done)
450450
})
451451

452+
it('transition with v-show, inside child component', done => {
453+
const vm = new Vue({
454+
template: `
455+
<div>
456+
<test v-show="ok"></test>
457+
</div>
458+
`,
459+
data: { ok: true },
460+
components: {
461+
test: {
462+
template: `<transition name="test"><div class="test">foo</div></transition>`
463+
}
464+
}
465+
}).$mount(el)
466+
467+
// should not apply transition on initial render by default
468+
expect(vm.$el.textContent).toBe('foo')
469+
expect(vm.$el.children[0].style.display).toBe('')
470+
vm.ok = false
471+
waitForUpdate(() => {
472+
expect(vm.$el.children[0].className).toBe('test test-leave test-leave-active')
473+
}).thenWaitFor(nextFrame).then(() => {
474+
expect(vm.$el.children[0].className).toBe('test test-leave-active')
475+
}).thenWaitFor(duration + 10).then(() => {
476+
expect(vm.$el.children[0].style.display).toBe('none')
477+
vm.ok = true
478+
}).then(() => {
479+
expect(vm.$el.children[0].style.display).toBe('')
480+
expect(vm.$el.children[0].className).toBe('test test-enter test-enter-active')
481+
}).thenWaitFor(nextFrame).then(() => {
482+
expect(vm.$el.children[0].className).toBe('test test-enter-active')
483+
}).thenWaitFor(duration + 10).then(() => {
484+
expect(vm.$el.children[0].className).toBe('test')
485+
}).then(done)
486+
})
487+
452488
it('leaveCancelled (v-show only)', done => {
453489
const spy = jasmine.createSpy('leaveCancelled')
454490
const vm = new Vue({
@@ -668,6 +704,44 @@ if (!isIE9) {
668704
}).then(done)
669705
})
670706

707+
it('transition inside child component', done => {
708+
const vm = new Vue({
709+
template: `
710+
<div>
711+
<test v-if="ok" class="test"></test>
712+
</div>
713+
`,
714+
data: { ok: true },
715+
components: {
716+
test: {
717+
template: `
718+
<transition>
719+
<div>foo</div>
720+
</transition>
721+
`
722+
}
723+
}
724+
}).$mount(el)
725+
726+
// should not apply transition on initial render by default
727+
expect(vm.$el.innerHTML).toBe('<div class="test">foo</div>')
728+
vm.ok = false
729+
waitForUpdate(() => {
730+
expect(vm.$el.children[0].className).toBe('test v-leave v-leave-active')
731+
}).thenWaitFor(nextFrame).then(() => {
732+
expect(vm.$el.children[0].className).toBe('test v-leave-active')
733+
}).thenWaitFor(duration + 10).then(() => {
734+
expect(vm.$el.children.length).toBe(0)
735+
vm.ok = true
736+
}).then(() => {
737+
expect(vm.$el.children[0].className).toBe('test v-enter v-enter-active')
738+
}).thenWaitFor(nextFrame).then(() => {
739+
expect(vm.$el.children[0].className).toBe('test v-enter-active')
740+
}).thenWaitFor(duration + 10).then(() => {
741+
expect(vm.$el.children[0].className).toBe('test')
742+
}).then(done)
743+
})
744+
671745
it('custom transition higher-order component', done => {
672746
const vm = new Vue({
673747
template: '<div><my-transition><div v-if="ok" class="test">foo</div></my-transition></div>',

0 commit comments

Comments
 (0)