首页 > 编程笔记

Vue v-if和v-else实现多元素过渡

在实战项目中,可以使用 v-if/v-else 控制多个元素标签的过渡。最常见的多标签过渡是一个列表和描述这个列表为空消息的元素,代码如下:
<transition>
  <table v-if="items.length > 0">
    <!-- 表格内容 -->
  </table>
  <p v-else>Sorry, no items found.</p>
</transition>
但是有一点需要注意,当有相同标签名的元素进行切换时,需要通过 key attribute 设置唯一的值来标记,以让 Vue.js 区分它们,否则 Vue.js 为了效率只会替换相同标签内部的内容。

即使在技术上没有必要,给在 transition 组件中的多个元素设置 key 是一个更好的实践,代码如下:
<transition>
  <button v-if="isEditing" key="save">
    Save
  </button>

  <button v-else key="edit">
    Edit
  </button>
</transition>

在一些场景中,也可以通过给同一个元素的 key attribute 设置不同的状态来代替 v-if 和 v-else,上面的例子可以重写,代码如下:
<transition>
  <button v-bind:key="isEditing">
    {{ isEditing ? 'Save' : 'Edit' }}
  </button>
</transition>

使用多个 v-if 的多个元素的过渡可以重写为绑定了动态 property 的单个元素的过渡,代码如下:
<transition>
  <button v-if="docState === 'saved'" key="saved">
    Edit
  </button>
  <button v-if="docState === 'edited'" key="edited">
    Save
  </button>
  <button v-if="docState === 'editing'" key="editing">
    Cancel
  </button>
</transition>

可以重写,代码如下:
<transition>
  <button v-bind:key="docState">
    {{ buttonMessage }}
  </button>
</transition>
...
computed: {
  buttonMessage: function() {
    switch (this.docState) {
      case 'saved':
        return 'Edit';
      case 'edited':
        return 'Save';
      case 'editing':
        return 'Cancel';
    }
  }
}

在实战中,经常需要实现在一个位置上两个元素可以相互替换(一个隐藏,另一个显示),Vue.js 对这两个元素的进入和离开是同时控制的,代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <!-- 引入 Vue.js -->
  <script src="../static/js/Vue.js" type="text/JavaScript"></script>
  <title>Demo vue</title>
</head>
<body>
  <!--定义 Vue.js 的视图 -->
  <div id="app">
    <transition>
      <!-- 当 show 为 true 时显示 "on" 按钮,否则显示 "off" 按钮 -->
      <button @click="show = !show" v-if="show" :key="1" style="position:absolute;">on</button>
      <button @click="show = !show" v-else :key="2" style="position: absolute;">off</button>
    </transition>
  </div>

  <script type="text/JavaScript">
    //创建 Vue.js 对象
    const vm = new Vue({
      el: "#app",
      data: {
        show: true
      }
    });
  </script>

  <style type="text/css">
    .v-enter-active {
      transition: all .3s ease;
    }
    .v-leave-active {
      transition: all .3s cubic-bezier(1.0, 0.5, 0.8, 1.0);
    }
    .v-enter /* .v-leave-active 用于低于版本 2.1.8 */{
      transform: translateX(40px);
      opacity: 0;
    }
    .v-leave-to{
      transform: translateX(-40px);
      opacity: 0;
    }
  </style>
</body>
</html>
单击 On/Off 按钮的时候,On/Off 按钮的离开和进入是同时进行的。

为了提高用户体验,需要控制离开和进入的顺序,例如先离开,再进入。这时候就可以使用 transition 元素的 mode 属性,指定过渡模式,以此来控制是先离开再进入,还是先进入再离开。

mode 属性有两个值可以选择,分别是 in-out 和 out-in,分别表示先进入再离开模式和先离开再进入模式,代码如下:
...
<div id="app">
  <transition>
    <!-- 当show为true时显示"on"按钮,否则显示"off"按钮 -->
    <button @click="show = !show" v-if="show" :key="1" style="position: absolute;">on</button>
    <button @click="show = !show" v-else :key="2" style="position: absolute;">off</button>
  </transition>
</div>
...

推荐阅读