| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798 |
- import { warn } from 'core/util/index'
- import { noop, camelize } from 'shared/util'
- import { leave } from 'web/runtime/modules/transition'
- import { getRealChild, mergeVNodeHook } from 'core/vdom/helpers'
- export default {
- name: 'transition',
- props: {
- name: String,
- appear: Boolean,
- css: Boolean,
- mode: String,
- enterClass: String,
- leaveClass: String,
- enterActiveClass: String,
- leaveActiveClass: String,
- appearClass: String,
- appearActiveClass: String
- },
- _abstract: true,
- render (h) {
- const children = this.$slots.default && this.$slots.default.filter(c => c.tag)
- if (!children || !children.length) {
- return
- }
- if (process.env.NODE_ENV !== 'production' && children.length > 1) {
- warn(
- '<transition> can only be used on a single element. Use ' +
- '<transition-group> for lists.'
- )
- }
- const rawChild = children[0]
- // if this is a component root node and the compoennt's
- // parent container node also has transition, skip.
- if (this.$vnode.parent && this.$vnode.parent.data.transition) {
- return rawChild
- }
- // apply transition data to child
- // use getRealChild() to ignore abstract components e.g. keep-alive
- const child = getRealChild(rawChild)
- child.key = child.key || `__v${child.tag + this._uid}__`
- const data = (child.data || (child.data = {})).transition = {}
- // props
- for (const key in this.$options.propsData) {
- data[key] = this[key]
- }
- // events.
- // extract listeners and pass them directly to the transition methods
- const listeners = this.$options._parentListeners
- for (const key in listeners) {
- data[camelize(key)] = listeners[key].fn
- }
- // handle transition mode
- const mode = this.mode
- const oldRawChild = this._vnode
- const oldChild = getRealChild(oldRawChild)
- if (mode && oldChild && oldChild.data && oldChild.key !== child.key) {
- if (mode === 'out-in') {
- if (
- !oldChild.elm._leaveCb && // not already leaving
- oldChild.data.transition // not already left
- ) {
- leave(oldChild, () => {
- // mark left & avoid triggering leave transition again
- oldChild.data.transition = null
- this.$forceUpdate()
- })
- }
- // return old node if not left yet
- if (oldChild.data.transition) {
- return oldRawChild
- }
- } else if (mode === 'in-out') {
- let delayedLeave
- const performLeave = () => { delayedLeave() }
- mergeVNodeHook(data, 'afterEnter', performLeave)
- mergeVNodeHook(data, 'enterCancelled', performLeave)
- const oldData = oldChild.data.transition
- mergeVNodeHook(oldData, 'delayLeave', leave => {
- delayedLeave = leave
- })
- mergeVNodeHook(oldData, 'leaveCancelled', () => {
- delayedLeave = noop
- })
- } else if (process.env.NODE_ENV !== 'production') {
- warn('invalid <transition> mode: ' + mode)
- }
- }
- return rawChild
- }
- }
|