Skip to content

Commit

Permalink
fix(transition): consider async placeholder as valid child to return (v…
Browse files Browse the repository at this point in the history
  • Loading branch information
jkzing authored and ztlevi committed Feb 14, 2018
1 parent c69efbb commit 0d6cbff
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 6 deletions.
3 changes: 2 additions & 1 deletion src/core/vdom/helpers/get-first-component-child.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
/* @flow */

import { isDef } from 'shared/util'
import { isAsyncPlaceholder } from './is-async-placeholder'

export function getFirstComponentChild (children: ?Array<VNode>): ?VNode {
if (Array.isArray(children)) {
for (let i = 0; i < children.length; i++) {
const c = children[i]
if (isDef(c) && isDef(c.componentOptions)) {
if (isDef(c) && (isDef(c.componentOptions) || isAsyncPlaceholder(c))) {
return c
}
}
Expand Down
1 change: 1 addition & 0 deletions src/core/vdom/helpers/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ export * from './update-listeners'
export * from './normalize-children'
export * from './resolve-async-component'
export * from './get-first-component-child'
export * from './is-async-placeholder'
5 changes: 5 additions & 0 deletions src/core/vdom/helpers/is-async-placeholder.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/* @flow */

export function isAsyncPlaceholder (node: VNode): boolean {
return node.isComment && node.asyncFactory
}
10 changes: 5 additions & 5 deletions src/platforms/web/runtime/components/transition.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@

import { warn } from 'core/util/index'
import { camelize, extend, isPrimitive } from 'shared/util'
import { mergeVNodeHook, getFirstComponentChild } from 'core/vdom/helpers/index'
import {
mergeVNodeHook,
isAsyncPlaceholder,
getFirstComponentChild
} from 'core/vdom/helpers/index'

export const transitionProps = {
name: String,
Expand Down Expand Up @@ -72,10 +76,6 @@ function isSameChild (child: VNode, oldChild: VNode): boolean {
return oldChild.key === child.key && oldChild.tag === child.tag
}

function isAsyncPlaceholder (node: VNode): boolean {
return node.isComment && node.asyncFactory
}

export default {
name: 'transition',
props: transitionProps,
Expand Down
84 changes: 84 additions & 0 deletions test/unit/features/component/component-keep-alive.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -862,5 +862,89 @@ describe('Component keep-alive', () => {
)
}).then(done)
})

it('async components with transition-mode out-in', done => {
const barResolve = jasmine.createSpy('bar resolved')
let next
const foo = (resolve) => {
setTimeout(() => {
resolve(one)
Vue.nextTick(next)
}, duration / 2)
}
const bar = (resolve) => {
setTimeout(() => {
resolve(two)
barResolve()
}, duration / 2)
}
components = {
foo,
bar
}
const vm = new Vue({
template: `<div>
<transition name="test" mode="out-in" @after-enter="afterEnter" @after-leave="afterLeave">
<keep-alive>
<component :is="view" class="test"></component>
</keep-alive>
</transition>
</div>`,
data: {
view: 'foo'
},
components,
methods: {
afterEnter () {
next()
},
afterLeave () {
next()
}
}
}).$mount(el)
expect(vm.$el.textContent).toBe('')
next = () => {
assertHookCalls(one, [1, 1, 1, 0, 0])
assertHookCalls(two, [0, 0, 0, 0, 0])
waitForUpdate(() => {
expect(vm.$el.innerHTML).toBe(
'<div class="test test-enter test-enter-active">one</div>'
)
}).thenWaitFor(nextFrame).then(() => {
expect(vm.$el.innerHTML).toBe(
'<div class="test test-enter-active test-enter-to">one</div>'
)
}).thenWaitFor(_next => { next = _next }).then(() => {
// foo afterEnter get called
expect(vm.$el.innerHTML).toBe('<div class="test">one</div>')
vm.view = 'bar'
}).thenWaitFor(nextFrame).then(() => {
assertHookCalls(one, [1, 1, 1, 1, 0])
assertHookCalls(two, [0, 0, 0, 0, 0])
expect(vm.$el.innerHTML).toBe(
'<div class="test test-leave-active test-leave-to">one</div><!---->'
)
}).thenWaitFor(_next => { next = _next }).then(() => {
// foo afterLeave get called
// and bar has already been resolved before afterLeave get called
expect(barResolve.calls.count()).toBe(1)
expect(vm.$el.innerHTML).toBe('<!---->')
}).thenWaitFor(nextFrame).then(() => {
expect(vm.$el.innerHTML).toBe(
'<div class="test test-enter test-enter-active">two</div>'
)
assertHookCalls(one, [1, 1, 1, 1, 0])
assertHookCalls(two, [1, 1, 1, 0, 0])
}).thenWaitFor(nextFrame).then(() => {
expect(vm.$el.innerHTML).toBe(
'<div class="test test-enter-active test-enter-to">two</div>'
)
}).thenWaitFor(_next => { next = _next }).then(() => {
// bar afterEnter get called
expect(vm.$el.innerHTML).toBe('<div class="test">two</div>')
}).then(done)
}
})
}
})

0 comments on commit 0d6cbff

Please sign in to comment.