Vue中多元素过渡特效的解决方案


Posted in Javascript onFebruary 05, 2020

常见示例

最常见的多标签过渡是一个列表和描述这个列表为空消息的元素:

<transition>
 <table v-if="items.length > 0">
  <!-- ... -->
 </table>
 <p v-else>Sorry, no items found.</p>
</transition>

下面是一个例子

<style>
.fade-enter,.fade-leave-to{opacity:0;}
.fade-enter-active,.fade-leave-active{transition:opacity .5s;}
</style>
<div id="demo">
 <button @click="clear">清空数据</button> 
 <button @click="reset">重置</button>  
 <transition name="fade">
  <ul v-if="items.length > 0">
   <li v-for="item in items">{{item}}</li>
  </ul>
  <p v-else>Sorry, no items found.</p>
 </transition>
</div>
<script>
new Vue({
 el: '#demo',
 data: {
  items: ['html','css','js']
 },
 methods:{
  clear(){
   this.items.splice(0);
  },
  reset(){
   history.go();
  }
 }
})
</script>

同标签名称

如果是相同标签名的元素切换时,Vue 为了效率只会替换相同标签内部的内容

<style>
.fade-enter,.fade-leave-to{opacity:0;}
.fade-enter-active,.fade-leave-active{transition:opacity .5s;}
</style>
<div id="demo">
 <button @click="show = !show">toggle</button>  
 <transition name="fade">
  <p v-if="show">Jb51</p>
  <p v-else>JB51</p>
 </transition>
</div>
<script>
new Vue({
 el: '#demo',
 data: {
  show:true
 },
})
</script>

由下面的示例可知,两个相同的p元素切换时,无过渡效果

因此,对于具有相同标签名的元素切换的情况,需要通过 key 特性设置唯一的值来标记以让 Vue 区分它们 

<div id="demo">
 <button @click="show = !show">toggle</button>  
 <transition name="fade">
  <p v-if="show" key="trueMatch">Jb51</p>
  <p v-else key="falseMatch">JB51</p>
 </transition>
</div>

替代if

在一些场景中,可以给通过给同一个元素的 key 特性设置不同的状态来代替 v-if 和 v-else

<transition>
 <button v-if="isEditing" key="save">Save</button>
 <button v-else key="edit">Edit</button>
</transition>

上面的例子可以重写为

<transition>
 <button v-bind:key="isEditing">
  {{ isEditing ? 'Save' : 'Edit' }}
 </button>
</transition>

下面是一个例子

<style>
.fade-enter,.fade-leave-to{opacity:0;}
.fade-enter-active,.fade-leave-active{transition:opacity .5s;}
</style>
<div id="demo">
 <button @click="isEditing = !isEditing">toggle</button>  
 <transition name="fade">
  <p v-bind:key="isEditing">
   {{ isEditing ? 'Save' : 'Edit' }}
  </p>
 </transition>
</div>
<script>
new Vue({
 el: '#demo',
 data: {
  isEditing:true
 },
})
</script>

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

<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'
  }
 }
}

下面是一个例子

<style>
.fade-enter,.fade-leave-to{opacity:0;}
.fade-enter-active,.fade-leave-active{transition:opacity .5s;}
</style>
<div id="demo">
 <button @click="change">change</button>  
 <transition name="fade">
  <p v-bind:key="docState">{{ message }}</p>
 </transition>
</div>
<script>
new Vue({
 el: '#demo',
 data: {
  index:0,
  isEditing:true,
  arr:['saved','edited','editing']
 },
 computed: {
  docState(){
   return this.arr[this.index];
  },
  message() {
   switch (this.docState) {
    case 'saved': return 'Edit'
    case 'edited': return 'Save'
    case 'editing': return 'Cancel'
   }
  }
 },
 methods:{
  change(){
   this.index = (++this.index)%3;
  }
 } 
})
</script>

过渡模式

先看下面这个例子

<style>
.fade-enter,.fade-leave-to{opacity:0;}
.fade-enter-active,.fade-leave-active{transition:opacity .5s;}
</style>
<div id="demo">  
 <transition name="fade">
  <button :key="isOn" @click="isOn = !isOn">{{ isOn ? 'On' : 'Off' }}</button>
 </transition>
</div>
<script>
new Vue({
 el: '#demo',
 data: {
  isOn: true
 },
})
</script>

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

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

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

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

in-out

下面使用in-out来重写之前的开关按钮过渡

<div id="demo">  
 <transition name="fade" mode="in-out">
  <button :key="isOn" @click="isOn = !isOn">{{ isOn ? 'On' : 'Off' }}</button>
 </transition>
</div>

out-in

下面使用out-in来重写之前的开关按钮过渡

<div id="demo">  
 <transition name="fade" mode="out-in">
  <button :key="isOn" @click="isOn = !isOn">{{ isOn ? 'On' : 'Off' }}</button>
 </transition>
</div>

滑动过渡

当元素设置为绝对定位,并互相覆盖,实现透明度过渡效果

<style>
#demo{position:relative;}
#demo button{position:absolute;left:40px;}
.fade-enter,.fade-leave-to{opacity:0;}
.fade-enter-active,.fade-leave-active{transition: 1s;}
</style>
<div id="demo">  
 <transition name="fade" >
  <button :key="isOn" @click="isOn = !isOn">{{ isOn ? 'On' : 'Off' }}</button>
 </transition>
</div>
<script>
new Vue({
 el: '#demo',
 data: {
  isOn: true
 },
})
</script>

下面是一个使用absolute和translate实现的类似滑动 

<style>
#demo{position:relative;}
#demo button{position:absolute;left:40px;}
.fade-enter,.fade-leave-to{opacity:0;}
.fade-enter{transform:translateX(30px);}
.fade-leave-to{transform:translateX(-30px);} 
.fade-enter-active,.fade-leave-active{transition: 1s;}
</style>

如果设置in-out模式,将实现更酷的滑动效果

<style>
#demo{position:relative;}
#demo button{position:absolute;left:40px;}
.fade-enter,.fade-leave-to{opacity:0;}
.fade-enter{transform:translateX(30px);}
.fade-leave-to{transform:translateX(-30px);} 
.fade-enter-active,.fade-leave-active{transition: 1s;}
</style>
<div id="demo">  
 <transition name="fade" mode="in-out">
  <button :key="isOn" @click="isOn = !isOn">{{ isOn ? 'On' : 'Off' }}</button>
 </transition>
</div>
<script>
new Vue({
 el: '#demo',
 data: {
  isOn: true
 },
})
</script>

多组件过渡

多个组件的过渡简单很多,不需要使用 key 特性。相反,只需要使用动态组件

下面是一个例子

<style>
.fade-enter,.fade-leave-to{opacity:0;}
.fade-enter-active,.fade-leave-active{transition: .5s;}
</style>
<div id="example">
 <button @click="change">切换页面</button>
 <transition name="fade" mode="out-in">
  <component :is="currentView"></component>
 </transition>
</div>
<script>
new Vue({
 el: '#example',
 data:{
  index:0,
  arr:[
   {template:`<div>ComponentA</div>`},
   {template:`<div>ComponentB</div>`},
   {template:`<div>ComponentC</div>`}
  ],
 },
 computed:{
  currentView(){
    return this.arr[this.index];
  }
 },
 methods:{
  change(){
   this.index = (++this.index)%3;
  }
 }
})

更多关于Vue过渡动画的文章大家可以查看下面的相关链接

Javascript 相关文章推荐
需要做特殊处理的DOM元素属性的访问
Nov 05 Javascript
多个表单中如何获得这个文件上传的网址实现js代码
Mar 25 Javascript
浏览器页面区域大小的js获取方法
Sep 21 Javascript
javascript生成随机数的方法
May 16 Javascript
javascript中setTimeout使用指南
Jul 26 Javascript
Vue2实现组件props双向绑定
Dec 02 Javascript
JS实现图片垂直居中显示小结
Dec 13 Javascript
angular5 子组件监听父组件传入值的变化方法
Sep 30 Javascript
elementUI Tree 树形控件的官方使用文档
Apr 25 Javascript
layui表格设计以及数据初始化详解
Oct 26 Javascript
Javascript实现秒表计时游戏
May 27 Javascript
JS字符串补全方法padStart()和padEnd()
May 27 Javascript
Vue路由管理器Vue-router的使用方法详解
Feb 05 #Javascript
Vue的状态管理vuex使用方法详解
Feb 05 #Javascript
浅谈Vue组件单元测试究竟测试什么
Feb 05 #Javascript
VUE中使用HTTP库Axios方法详解
Feb 05 #Javascript
Vue获取页面元素的相对位置的方法示例
Feb 05 #Javascript
vue.js使用v-model实现父子组件间的双向通信示例
Feb 05 #Javascript
vue使用原生swiper代码实例
Feb 05 #Javascript
You might like
PHP中实现汉字转区位码应用源码实例解析
2010/06/14 PHP
Drupal7连接多个数据库及常见问题解决
2014/03/02 PHP
Laravel使用Caching缓存数据减轻数据库查询压力的方法
2016/03/15 PHP
thinkPHP5.0框架验证码调用及点击图片刷新简单实现方法
2018/09/07 PHP
IE6浏览器下resize事件被执行了多次解决方法
2012/12/11 Javascript
JQuery+DIV自定义滚动条样式的具体实现
2013/06/25 Javascript
JS中prototype关键字的功能介绍及使用示例
2013/07/21 Javascript
轻松创建nodejs服务器(3):代码模块化
2014/12/18 NodeJs
JavaScript原生对象之String对象的属性和方法详解
2015/03/13 Javascript
jquery获取多个checkbox的值异步提交给php
2015/07/07 Javascript
javascript常用的设计模式
2017/02/09 Javascript
JS实现复选框的全选和批量删除功能
2017/04/05 Javascript
探索webpack模块及webpack3新特性
2017/09/18 Javascript
JS数组求和的常用方法总结【5种方法】
2019/01/14 Javascript
Python中线程的MQ消息队列实现以及消息队列的优点解析
2016/06/29 Python
python类中super()和__init__()的区别
2016/10/18 Python
Python中的pack和unpack的使用
2018/03/12 Python
解决pip install的时候报错timed out的问题
2018/06/12 Python
Python读取指定日期邮件的实例
2019/02/01 Python
Python3.5内置模块之random模块用法实例分析
2019/04/26 Python
Python判断远程服务器上Excel文件是否被人打开的方法
2020/07/13 Python
CSS3 滤镜 webkit-filter详细介绍及使用方法
2012/12/27 HTML / CSS
html5模拟平抛运动(模拟小球平抛运动过程)
2013/07/25 HTML / CSS
台湾家适得:Homeget
2019/02/11 全球购物
十月份红领巾广播稿
2014/01/22 职场文书
西式婚礼主持词
2014/03/13 职场文书
在职证明书范本(2014新版)
2014/09/25 职场文书
2014年化验室工作总结
2014/11/21 职场文书
会计人员岗位职责
2015/02/03 职场文书
工商局个人工作总结
2015/03/03 职场文书
中学生清明节演讲稿
2015/03/18 职场文书
结婚典礼致辞
2015/07/28 职场文书
安全主题班会教案
2015/08/12 职场文书
MySQL数字类型自增的坑
2021/05/07 MySQL
详解Redis基本命令与使用场景
2021/06/01 Redis
python人工智能human learn绘图可创建机器学习模型
2021/11/23 Python