多个元素或组件的过渡/动画效果
在前面的演示代码中,使用 transition
组件实现过渡/动画效果时,都是只给 transition
组件内的一个 <div>
元素套用了动画效果。在 Vue
中,同样支持给多个元素添加过渡/动画效果。下面还是以之前的过渡/动画演示代码为例,如示例代码 5-6-1 所示。
.fade-enter,.fade-leave-to {
opacity: 0
}
.fade-enter-active,.fade-leave-active {
transition: opacity 2s
}
<div id="app">
<button @click="clickCallback">切换</button>
<transition name="fade">
<div v-if="show">Hello!</div>
<div v-else>World!</div>
</transition>
</div>
从上面的代码可知,在 transition
组件中定义了两个 <div>
子元素,并分别使用 v-if
和 v-else
来控制显示和隐藏,同时将 fade
的过渡效果套用到这两个子元素中。但是,当运行代码时,并没有出现:Hello!
显示、World!隐藏或者 Hello!隐藏、World!显示这些效果。这是为什么呢?
当有相同标签名的元素切换时,正如示例代码中的两个子元素都采用的是 <div>
,Vue
为了效率,只会替换相同标签内部的内容,而不会整体替换,需要通过 key
属性设置唯一的值来标记,以让 Vue
区分它们。所以,需要给每个 div
设置一个唯一的 key
值,代码如下:
<transition name="fade">
<div v-if="show" key="a">Hello!</div>
<div v-else key="b">World!</div>
</transition>
再次运行这段代码,就可以看到动画效果,但是目前的动画效果还不是最完美的效果。在 Hello!显示、World!隐藏或者 Hello!隐藏、World!显示时,两个元素会发生重叠,也就是说一个 <div>
元素在执行离开过渡,同时另一个 <div>
元素在执行进入过渡,这是 transition
组件的默认行为:进入和离开同时发生。针对这个问题,transition
组件提供了过渡模式 mode
的设置项:
-
in-out
:新元素先进行过渡,完成之后当前元素过渡离开。 -
out-in
:当前元素先进行过渡,完成之后新元素过渡进入。
可以尝试将 mode
设置成 out-in
来看看效果,代码如下:
<transition name="fade" mode="out-in">...</transition>
通过上面的配置,再次运行动画代码,就不会再发生重叠现象。<transition>
不仅可以为多个 <div>
等原生的 HTML
元素添加过渡/动画效果,对于多个不同的自定义组件也可以使用。另外,切换组件除了使用 v-if
或者 v-show
之外,也可以使用动态组件 <component>
来实现不同组件的替换,如示例代码 5-6-2 所示。
<style type="text/css">
.component-fade-enter-active, .component-fade-leave-active {
transition: opacity .3s ease;
}
.component-fade-enter-from, .component-fade-leave-to {
opacity: 0;
}
</style>
...
<div id="app">
<button @click="clickCallback">切换</button>
<transition name="component-fade" mode="out-in">
<component :is="view"></component>
</transition>
</div>
...
Vue.createApp({
data() {
return {
view: 'a',
count: 0
}
},
components: {
'a': { // 子组件A
template: '<div>Component A</div>'
},
'b': {// 子组件B
template: '<div>Component B</div>'
}
},
methods:{
clickCallback(){
if (this.count % 2 == 1) {
this.view = 'a'
} else {
this.view = 'b'
}
this.count++
}
}
}).mount("#app")
上面的代码中,<transition>
组件中只包含一个 <component>
组件,但是可以通过 v-bind
指令加 is
来实现不同组件的替换,并且应用上了过渡效果,读者可以在浏览器中运行体验。