Browse Source

fix v-show transition on child component root (fix #3354)

dev
Evan You 8 years ago
parent
commit
6e471ea2ee
  1. 13
      src/platforms/web/runtime/directives/show.js
  2. 74
      test/unit/features/transition/transition.spec.js

13
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)

74
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: `
<div>
<test v-show="ok"></test>
</div>
`,
data: { ok: true },
components: {
test: {
template: `<transition name="test"><div class="test">foo</div></transition>`
}
}
}).$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: `
<div>
<test v-if="ok" class="test"></test>
</div>
`,
data: { ok: true },
components: {
test: {
template: `
<transition>
<div>foo</div>
</transition>
`
}
}
}).$mount(el)
// should not apply transition on initial render by default
expect(vm.$el.innerHTML).toBe('<div class="test">foo</div>')
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: '<div><my-transition><div v-if="ok" class="test">foo</div></my-transition></div>',

Loading…
Cancel
Save