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 相关文章推荐
强制设为首页代码
Jun 19 Javascript
javascript框架设计读书笔记之模块加载系统
Dec 02 Javascript
jQuery中判断对象是否存在的方法汇总
Feb 24 Javascript
Javascript数组Array方法解读
Mar 13 Javascript
利用原生js和jQuery实现单选框的勾选和取消操作的方法
Sep 04 Javascript
浅谈js常用内置方法和对象
Sep 24 Javascript
JavaScript中cookie工具函数封装的示例代码
Oct 11 Javascript
详解JS-- 浮点数运算处理
Nov 28 Javascript
用director.js实现前端路由使用实例
Jan 27 Javascript
详解AngularJs路由之Ui-router-resolve(预加载)
Jun 13 Javascript
bootstrap treeview 树形菜单带复选框及级联选择功能
Jun 08 Javascript
深入理解javascript prototype的相关知识
Sep 19 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
yii实现CheckBox复选框在同一行显示的方法
2014/12/03 PHP
php获取字符串前几位的实例(substr返回字符串的子串用法)
2017/03/08 PHP
JS 自动安装exe程序
2008/11/30 Javascript
基于jQuery的表格操作插件
2010/04/22 Javascript
解决jQuery插件tipswindown与hintbox冲突
2010/11/05 Javascript
Javascript Boolean、Nnumber、String 强制类型转换的区别详细介绍
2012/12/13 Javascript
Javascript中arguments和arguments.callee的区别浅析
2015/04/24 Javascript
基于BootStrap Metronic开发框架经验小结【四】Bootstrap图标的提取和利用
2016/05/12 Javascript
JavaScript实现简单的日历效果
2016/09/25 Javascript
微信小程序 教程之小程序配置
2016/10/17 Javascript
Nodejs 发送Post请求功能(发短信验证码例子)
2017/02/09 NodeJs
jQuery简单实现MD5加密的方法
2017/03/03 Javascript
vue 和vue-touch 实现移动端左右导航效果(仿京东移动站导航)
2017/04/22 Javascript
jQuery插件实现的日历功能示例【附源码下载】
2018/09/07 jQuery
老生常谈JavaScript获取CSS样式的方法(兼容各浏览器)
2018/09/19 Javascript
详解axios中封装使用、拦截特定请求、判断所有请求加载完毕)
2019/04/09 Javascript
[01:13]2015国际邀请赛线下观战现场
2015/08/08 DOTA
python对字典进行排序实例
2014/09/25 Python
python实现根据窗口标题调用窗口的方法
2015/03/13 Python
在Python的Tornado框架中实现简单的在线代理的教程
2015/05/02 Python
Python读写txt文本文件的操作方法全解析
2016/06/26 Python
Python函数的周期性执行实现方法
2016/08/13 Python
python3+PyQt5 使用三种不同的简便项窗口部件显示数据的方法
2019/06/17 Python
Python生态圈图像格式转换问题(推荐)
2019/12/02 Python
CSS3 实现footer 固定在底部(无论页面多高始终在底部)
2019/10/15 HTML / CSS
Speedo速比涛法国官方网站:泳衣、泳镜、泳帽、泳裤
2019/07/30 全球购物
惠而浦美国官网:Whirlpool.com
2021/01/19 全球购物
英语系本科生求职信范文
2013/12/18 职场文书
优秀团支部申报材料
2014/12/26 职场文书
八年级英语教学计划
2015/01/23 职场文书
个人工作能力自我评价
2015/03/05 职场文书
工作态度恶劣检讨书
2015/05/06 职场文书
通用员工手册范本
2015/05/14 职场文书
Python利用folium实现地图可视化
2021/05/23 Python
Python NumPy灰度图像的压缩原理讲解
2021/08/04 Python
tomcat正常启动但网页却无法访问的几种解决方法
2022/05/06 Servers