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 相关文章推荐
js 获取后台的字段 改变 checkbox的被选中的状态 代码
Jun 05 Javascript
JS 获取滚动条高度示例代码
Oct 24 Javascript
js实现在字符串中提取数字
Nov 05 Javascript
浅析IE10兼容性问题(frameset的cols属性)
Jan 03 Javascript
Javascript 按位左移运算符使用介绍(
Feb 04 Javascript
js动态修改整个页面样式达到换肤效果
May 23 Javascript
js中将String转换为number以便比较
Jul 08 Javascript
js省市区级联查询(插件版&amp;无插件版)
Mar 21 Javascript
JavaScript实现简单的树形菜单效果
Jun 23 Javascript
JavaScript获取移动设备型号的实现代码(JS获取手机型号和系统)
Mar 10 Javascript
微信小程序可滑动周日历组件使用详解
Oct 21 Javascript
解决vuex改变了state的值,但是页面没有更新的问题
Nov 12 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
15种PHP Encoder的比较
2007/04/17 PHP
PHP中关于php.ini参数优化详解
2020/02/28 PHP
兼容IE和FF的js脚本代码小结(比较常用)
2010/12/06 Javascript
一个JavaScript处理textarea中的字符成每一行实例
2014/09/22 Javascript
基于jQuery实现复选框是否选中进行答题提示
2015/12/10 Javascript
jquery实现手机端单店铺购物车结算删除功能
2017/02/22 Javascript
JavaScript使用readAsDataURL读取图像文件
2017/05/10 Javascript
Node.js  事件循环详解及实例
2017/08/06 Javascript
详解ES6中的三种异步解决方案
2018/06/28 Javascript
Vue一个案例引发的递归组件的使用详解
2018/11/15 Javascript
vue.js表单验证插件(vee-validate)的使用教程详解
2019/05/23 Javascript
使用JS来动态操作css的几种方法
2019/12/18 Javascript
vue实现匀速轮播效果
2020/06/29 Javascript
使用go和python递归删除.ds store文件的方法
2014/01/22 Python
pycharm 使用心得(四)显示行号
2014/06/05 Python
分析Python的Django框架的运行方式及处理流程
2015/04/08 Python
Python实现加载及解析properties配置文件的方法
2018/03/29 Python
Python实现二叉树的常见遍历操作总结【7种方法】
2019/03/06 Python
python多线程下信号处理程序示例
2019/05/31 Python
Python识别html主要文本框过程解析
2020/02/18 Python
Python中格式化字符串的四种实现
2020/05/26 Python
浅谈opencv自动光学检测、目标分割和检测(连通区域和findContours)
2020/06/04 Python
如何在python中判断变量的类型
2020/07/29 Python
日本面向世界,国际级的免税在线购物商城:DOKODEMO
2017/02/01 全球购物
美国婚戒购物网站:Anjays Designs
2017/06/28 全球购物
中专毕业生自荐信
2013/11/16 职场文书
后勤岗位职责
2013/11/26 职场文书
实习教师自我鉴定
2013/12/09 职场文书
高校十八大报告感想
2014/01/27 职场文书
教师群众路线教育实践活动学习笔记
2014/11/05 职场文书
2014年小学德育工作总结
2014/12/05 职场文书
工程质量保证书
2015/05/09 职场文书
2016抗战胜利71周年红领巾广播稿
2015/12/18 职场文书
vue如何批量引入组件、注册和使用详解
2021/05/12 Vue.js
JavaScript选择器函数querySelector和querySelectorAll
2021/11/27 Javascript
详解Android中的TimePickerView(时间选择器)的用法
2022/04/30 Java/Android