对于transition这个单词,大家应该不陌生,在css3中transition属性被用于描述css属性的过渡效果。在vue中,使用了同名的transition组件,其目的也显而易见了,是为了提供易于使用的组件级别的过渡效果。
一、transition组件使用示例
先看一下transition的简单使用示例
<template>
<div id="app">
<button v-on:click="show = !show">Toggle</button>
<transition name="fade">
<p v-if="show">hello</p>
</transition>
</div>
</template>
<script>
export default {
name: "App",
data() {
return {
show: true
};
}
};
</script>
<style>
#app {
text-align: center;
margin-top: 60px;
}
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.5s;
}
.fade-enter, .fade-leave-to {
opacity: 0;
}
</style>
效果展示:

可以看到在点击Toggle后,hello的出现和消失具有动画效果。
我们来看一下DOM

DOM中不存在transition组件对应的元素节点,这一点在vue的官方文档上有说明:<transition>只会把过渡效果应用到其包裹的内容上,而不会额外渲染 DOM 元素,也不会出现在可被检查的组件层级中。
二、transition组件源码
需要说明的是transition的源码并不在src/core目录下,而是在src/platforms目录下,这说明web和weex平台对于transition的实现并不一致,这里我们只关注web平台下的实现。
// vue源码\src\platforms\web\runtime\components\transition.js
// 为了便于理解,只保留了部分代码
export default {
name: 'transition',
props: transitionProps,
abstract: true,
render (h: Function) {
let children: any = this.$slots.default
if (!children) {
return
}
// filter out text nodes (possible whitespaces)
children = children.filter(isNotTextNode)
if (!children.length) {
return
}
const rawChild: VNode = children[0]
// apply transition data to child
// use getRealChild() to ignore abstract components e.g. keep-alive
const child: ?VNode = getRealChild(rawChild)
if (!child) {
return rawChild
}
// 核心代码
const data: Object = (child.data || (child.data = {})).transition = extractTransitionData(this)
return rawChild
}
}
注意:上面的代码中,只保留了目前我们需要的核心源码。
在代码中abstract:true表示transition是一个抽象组件,并且其render函数中返回的是child节点,因此transition组件本身并不会在DOM上有任何渲染。
在上面代码中核心是第30行,其给child节点的data上添加了一个transition属性,我们看一下extractTransitionData的代码:
// vue源码\src\platforms\web\runtime\components\transition.js
export function extractTransitionData (comp: Component): Object {
const data = {}
const options: ComponentOptions = comp.$options
// props
for (const key in options.propsData) {
data[key] = comp[key]
}
// events.
// extract listeners and pass them directly to the transition methods
const listeners: ?Object = options._parentListeners
for (const key in listeners) {
data[camelize(key)] = listeners[key]
}
return data
}
extractTransitionData的代码很简单,就是将绑定在transition组件上的属性和事件提取出来,组合成一个数据对象。
三、总结
总结来说,transition是vue内置的一个抽象组件,在transition组件渲染时会将绑定在transition自身的属性和事件组合成一个对象,并将该对象绑定在transition子组件的data.transition属性上。
那么可以猜测的是:子组件渲染时会根据其data.transition属性添加对应的过渡class及触发相应事件,从而达到示例中的效果。那么这个过程具体是如何进行的,我们下一篇文章再探讨吧。