多个元素的过渡

我们之后讨论多个组件的过渡,对于原生标签可以使用 v-if/v-else 。最常见的多标签过渡是一个列表和描述这个列表为空消息的元素:

  1. <transition>
  2. <table v-if="items.length > 0">
  3. <!-- ... -->
  4. </table>
  5. <p v-else>Sorry, no items found.</p>
  6. </transition>

可以这样使用,但是有一点需要注意:

当有相同标签名的元素切换时,需要通过 key 特性设置唯一的值来标记以让 Vue 区分它们,否则 Vue 为了效率只会替换相同标签内部的内容。即使在技术上没有必要,给在 <transition> 组件中的多个元素设置 key 是一个更好的实践。

示例:

  1. <transition>
  2. <button v-if="isEditing" key="save">
  3. Save
  4. </button>
  5. <button v-else key="edit">
  6. Edit
  7. </button>
  8. </transition>

在一些场景中,也可以通过给同一个元素的 key 特性设置不同的状态来代替 v-ifv-else,上面的例子可以重写为:

  1. <transition>
  2. <button v-bind:key="isEditing">
  3. {{ isEditing ? 'Save' : 'Edit' }}
  4. </button>
  5. </transition>

使用多个 v-if 的多个元素的过渡可以重写为绑定了动态属性的单个元素过渡。例如:

  1. <transition>
  2. <button v-if="docState === 'saved'" key="saved">
  3. Edit
  4. </button>
  5. <button v-if="docState === 'edited'" key="edited">
  6. Save
  7. </button>
  8. <button v-if="docState === 'editing'" key="editing">
  9. Cancel
  10. </button>
  11. </transition>

可以重写为:

  1. <transition>
  2. <button v-bind:key="docState">
  3. {{ buttonMessage }}
  4. </button>
  5. </transition>
  1. // ...
  2. computed: {
  3. buttonMessage: function () {
  4. switch (this.docState) {
  5. case 'saved': return 'Edit'
  6. case 'edited': return 'Save'
  7. case 'editing': return 'Cancel'
  8. }
  9. }
  10. }

过渡模式

这里还有一个问题,试着点击下面的按钮:

多个元素的过渡 - 图1

在 “on” 按钮和 “off” 按钮的过渡中,两个按钮都被重绘了,一个离开过渡的时候另一个开始进入过渡。这是 <transition> 的默认行为 - 进入和离开同时发生。

在元素绝对定位在彼此之上的时候运行正常:

多个元素的过渡 - 图2

然后,我们加上 translate 让它们运动像滑动过渡:

多个元素的过渡 - 图3

同时生效的进入和离开的过渡不能满足所有要求,所以 Vue 提供了 过渡模式

  • in-out:新元素先进行过渡,完成之后当前元素过渡离开。

  • out-in:当前元素先进行过渡,完成之后新元素过渡进入。

out-in 重写之前的开关按钮过渡:

  1. <transition name="fade" mode="out-in">
  2. <!-- ... the buttons ... -->
  3. </transition>

多个元素的过渡 - 图4

只用添加一个简单的特性,就解决了之前的过渡问题而无需任何额外的代码。

in-out 模式不是经常用到,但对于一些稍微不同的过渡效果还是有用的。将之前滑动淡出的例子结合:

多个元素的过渡 - 图5

很酷吧?