From 6e471ea2ee75cd85e1466b74014672619a3898b9 Mon Sep 17 00:00:00 2001 From: Evan You Date: Sun, 31 Jul 2016 17:31:02 -0400 Subject: [PATCH] fix v-show transition on child component root (fix #3354) --- src/platforms/web/runtime/directives/show.js | 13 +++- .../features/transition/transition.spec.js | 74 +++++++++++++++++++ 2 files changed, 85 insertions(+), 2 deletions(-) diff --git a/src/platforms/web/runtime/directives/show.js b/src/platforms/web/runtime/directives/show.js index 57ac3ed3..0dd9ec77 100644 --- a/src/platforms/web/runtime/directives/show.js +++ b/src/platforms/web/runtime/directives/show.js @@ -3,16 +3,25 @@ import { isIE9 } from 'web/util/index' import { enter, leave } from '../modules/transition' +// recursively search for possible transition defined inside the component root +function locateNode (vnode: VNode): VNodeWithData { + return vnode.child && (!vnode.data || !vnode.data.transition) + ? locateNode(vnode.child._vnode) + : vnode +} + export default { bind (el: HTMLElement, { value }: VNodeDirective, vnode: VNodeWithData) { - const transition = vnode.data.transition + vnode = locateNode(vnode) + const transition = vnode.data && vnode.data.transition if (value && transition && transition.appear && !isIE9) { enter(vnode) } el.style.display = value ? '' : 'none' }, update (el: HTMLElement, { value }: VNodeDirective, vnode: VNodeWithData) { - const transition = vnode.data.transition + vnode = locateNode(vnode) + const transition = vnode.data && vnode.data.transition if (transition && !isIE9) { if (value) { enter(vnode) diff --git a/test/unit/features/transition/transition.spec.js b/test/unit/features/transition/transition.spec.js index 8d406138..b47ac04d 100644 --- a/test/unit/features/transition/transition.spec.js +++ b/test/unit/features/transition/transition.spec.js @@ -449,6 +449,42 @@ if (!isIE9) { }).then(done) }) + it('transition with v-show, inside child component', done => { + const vm = new Vue({ + template: ` +
+ +
+ `, + data: { ok: true }, + components: { + test: { + template: `
foo
` + } + } + }).$mount(el) + + // should not apply transition on initial render by default + expect(vm.$el.textContent).toBe('foo') + expect(vm.$el.children[0].style.display).toBe('') + vm.ok = false + waitForUpdate(() => { + expect(vm.$el.children[0].className).toBe('test test-leave test-leave-active') + }).thenWaitFor(nextFrame).then(() => { + expect(vm.$el.children[0].className).toBe('test test-leave-active') + }).thenWaitFor(duration + 10).then(() => { + expect(vm.$el.children[0].style.display).toBe('none') + vm.ok = true + }).then(() => { + expect(vm.$el.children[0].style.display).toBe('') + expect(vm.$el.children[0].className).toBe('test test-enter test-enter-active') + }).thenWaitFor(nextFrame).then(() => { + expect(vm.$el.children[0].className).toBe('test test-enter-active') + }).thenWaitFor(duration + 10).then(() => { + expect(vm.$el.children[0].className).toBe('test') + }).then(done) + }) + it('leaveCancelled (v-show only)', done => { const spy = jasmine.createSpy('leaveCancelled') const vm = new Vue({ @@ -668,6 +704,44 @@ if (!isIE9) { }).then(done) }) + it('transition inside child component', done => { + const vm = new Vue({ + template: ` +
+ +
+ `, + data: { ok: true }, + components: { + test: { + template: ` + +
foo
+
+ ` + } + } + }).$mount(el) + + // should not apply transition on initial render by default + expect(vm.$el.innerHTML).toBe('
foo
') + vm.ok = false + waitForUpdate(() => { + expect(vm.$el.children[0].className).toBe('test v-leave v-leave-active') + }).thenWaitFor(nextFrame).then(() => { + expect(vm.$el.children[0].className).toBe('test v-leave-active') + }).thenWaitFor(duration + 10).then(() => { + expect(vm.$el.children.length).toBe(0) + vm.ok = true + }).then(() => { + expect(vm.$el.children[0].className).toBe('test v-enter v-enter-active') + }).thenWaitFor(nextFrame).then(() => { + expect(vm.$el.children[0].className).toBe('test v-enter-active') + }).thenWaitFor(duration + 10).then(() => { + expect(vm.$el.children[0].className).toBe('test') + }).then(done) + }) + it('custom transition higher-order component', done => { const vm = new Vue({ template: '
foo
',