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 相关文章推荐
Javascript 获取滚动条位置等信息的函数
Sep 08 Javascript
使用jquery中height()方法获取各种高度大全
Apr 02 Javascript
js使用setTimeout实现定时炸弹的方法
Apr 10 Javascript
js实现tab切换效果实例
Sep 16 Javascript
AngularJS 模块化详解及实例代码
Sep 14 Javascript
微信小程序 tabs选项卡效果的实现
Jan 05 Javascript
jquery.form.js异步提交表单详解
Apr 25 jQuery
vue中Npm run build 根据环境传递参数方法来打包不同域名
Mar 29 Javascript
Vue自定义指令封装节流函数的方法示例
Jul 09 Javascript
从0到1构建vueSSR项目之路由的构建
Mar 07 Javascript
wepy--用vantUI 实现上弹列表并选择相应的值操作
Nov 03 Javascript
vue实现按钮切换图片
Jan 20 Vue.js
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中构造函数和析构函数解析
2014/10/10 PHP
PHP之十六个魔术方法详细介绍
2016/11/01 PHP
php+ajax简单实现全选删除的方法
2016/12/06 PHP
PHP自定义递归函数实现数组转JSON功能【支持GBK编码】
2018/07/17 PHP
JScript中的undefined和&quot;undefined&quot;的区别
2007/03/08 Javascript
jQuery的attr与prop使用介绍
2013/10/10 Javascript
JS实现至少包含字母、大小写数字、字符的密码等级的两种方法
2015/02/03 Javascript
jquery实现根据浏览器窗口大小自动缩放图片的方法
2015/07/17 Javascript
js实现字符串和数组之间相互转换操作
2016/01/12 Javascript
jQuery 弹出层插件(推荐)
2016/05/24 Javascript
基于Bootstrap实现下拉菜单项和表单导航条(两个菜单项,一个下拉菜单和登录表单导航条)
2016/07/22 Javascript
JavaScript组件开发之输入框加候选框
2017/03/10 Javascript
nodejs中向HTTP响应传送进程的输出
2017/03/19 NodeJs
ES6入门教程之Iterator与for...of循环详解
2017/05/17 Javascript
swiper自定义分页器使用方法详解
2020/09/14 Javascript
移动端图片上传旋转、压缩问题的方法
2018/10/16 Javascript
关于微信公众号开发无法支付的问题解决
2018/12/28 Javascript
vue实现全匹配搜索列表内容
2019/09/26 Javascript
分享JS表单验证源码(带错误提示及密码等级)
2020/01/05 Javascript
vue路由权限校验功能的实现代码
2020/06/07 Javascript
vue $mount 和 el的区别说明
2020/09/11 Javascript
[52:31]VP vs Serenity 2018国际邀请赛小组赛BO2 第二场 8.16
2018/08/17 DOTA
[01:39:04]DOTA2-DPC中国联赛 正赛 SAG vs CDEC BO3 第二场 2月1日
2021/03/11 DOTA
python实现监控windows服务并自动启动服务示例
2014/04/17 Python
讲解Python中的递归函数
2015/04/27 Python
Python多进程与服务器并发原理及用法实例分析
2018/08/21 Python
Css3新特性应用之形状总结
2016/12/08 HTML / CSS
英国女性化妆品收纳和家具网站:Beautify
2019/12/07 全球购物
编程用JAVA解析XML的方式
2013/07/07 面试题
学校大课间活动方案
2014/01/30 职场文书
《两只鸟蛋》教学反思
2014/02/10 职场文书
2015年信息中心工作总结
2015/05/25 职场文书
安全伴我行主题班会
2015/08/13 职场文书
2016教师学习党章心得体会
2016/01/15 职场文书
Redis做数据持久化的解决方案及底层原理
2021/07/15 Redis
《金肉人》米特&《航海王》阿鹤声优松岛实因胰脏癌去世 享寿81岁
2022/04/13 日漫