1、Vue.js中的元素动画或页面跳转动画有多种实现方式比如:
1、自己手动写CSS3动画来实现
2、使用第三方CSS动画库如:Animate.css
3、在构子函数中操作DOM
4、使用第三方Js动画库如:Velocity.js
2、Vue.js官方提供了默认的动画组件 transition ,例子:
<div id="demo"> <button @click='show=!show'>切换</button> <transition name='fade'> //将需要执行动画的元素包裹在transition标签中,并制定动画名称 <p v-if='show'>Hello</p> </transition> </div> new Vue({ el:'demo', data:{ show:true } }) .fade-enter-active,.fade-leave-active{ transition:opacity .5s } .fade-enter,.fade-leave-to{ opacity:0 } transition执行:目标元素是否应用CSS过渡或动画(增删类名)-->调用构子函数
3、transition过渡的类名
状态A-->状态B
v-enter:元素初始状态
v-enter-to:动画结束后状态
v-enter-active:动画过渡过程,用来定义动画时间、延迟、曲线函数
状态B-->状态A
v-leave:返回动画执行前状态
v-leave-to:返回动画执行后状态
v-leave-active:返回动画过渡过程,用来定义动画时间、延迟、曲线函数
见官网图如下:( V 代表动画的类名)
4、使用CSS动画
1 <div id='demo'> 2 <button @click='show=!show'>切换</button> 3 <transition name='bounce'> 4 <p v-show='show'>Hello</p> 5 </transition> 6 </div> 7 8 new Vue({ 9 el:'#demo', 10 data:{ 11 show:true 12 } 13 }) 14 15 .bounce-enter-active{ 16 animation:bounce-in .5s; 17 } 18 .bounce-leave-active{ 19 animation:bounce-in .5s reverse; 20 } 21 22 @keyframes bounce{ 23 0%{ 24 transform:scale(0) 25 } 26 50%{ 27 transform:scale(1.5) 28 } 29 100%{ 30 transform:scale(1) 31 } 32 }
5、使用第三方CSS动画库 Animate.css
1 通过以下特性自定义过渡类名(可结合第三方CSS库): 2 enter-class 3 enter-to-class 4 enter-active-class 5 leave-active 6 leave-to-class 7 leave-active-class 8 9 <div id='demo'> 10 <button @click='show=!show'>切换</button> 11 <transition name='custom-classes-trandition' enter-active-class='animated tada' leave-active-class='animated bounceOutRight'> 12 <p>Hello</p> 13 </transition> 14 </div> 15 16 new Vue({ 17 el:'demo', 18 data:{ 19 show:true 20 } 21 })
6、动画过渡时间
<transition :duration="1000">...</transition> //设置1000毫秒时间 <transition :duration="{enter:500,leave:800}">...</transition> //设置进入时间和回退时间
7、Vue.js的JavaScript动画构子函数
<transition @before-enter='beforeEnter' @enter='enter' @after-enter='afterEnter' @enter-cancelled='enterCancelled' @before-leave='beforeLeave' @leave='leave' @after-leave='afterLeave' @leave-cancelled='leaveCancelled' :css='false' > </transition> //对于仅使用 JavaScript 过渡的元素添加 v-bind:css="false",Vue 会跳过 CSS 的检测 methods:{ beforeEnter:function(el){}, enter:function(el,done){ done(); //当只用 JavaScript 过渡的时候,在 enter 和 leave 中必须使用 done 进行回调 }, afterEnter:function(el){}, enterCancelled:function(el){}, beforeLeave:function(el){}, leave:function(el){ done(); }, afterLeave:function(el){}, leaveCancelled:function(el){} } //钩子函数可以结合 CSS transitions/animations 使用,也可以单独使用
8、使用第三方JavaScript动画库Velocity.js
<div id="demo"> <button @click="show = !show">切换</button> <transition @before-enter="beforeEnter" @enter="enter" @leave="leave" :css="false" > <p v-if="show">Hello</p> </transition> </div> new Vue({ el: '#demo', data: { show: false }, methods: { beforeEnter: function (el) { el.style.opacity = 0 el.style.transformOrigin = 'left' }, enter: function (el, done) { Velocity(el, { opacity: 1, fontSize: '1.4em' }, { duration: 300 }) Velocity(el, { fontSize: '1em' }, { complete: done }) }, leave: function (el, done) { Velocity(el, { translateX: '15px', rotateZ: '50deg' }, { duration: 600 }) Velocity(el, { rotateZ: '100deg' }, { loop: 2 }) Velocity(el, { rotateZ: '45deg', translateY: '30px', translateX: '30px', opacity: 0 }, { complete: done }) } } })
9、通过 appear 特性设置节点在初始渲染的过渡
<transition appear> </transition> 自定义过渡类名: <transition appear appear-class="custom-appear-class" appear-to-class="custom-appear-to-class" appear-active-class="custom-appear-active-class"> </transition> 自定义JavaScript构子: <transition appear @before-appear='BeforeAppearHook' @appear='AppearHook' @after-appear='AfterAppearHook' @appear-cancelled='AppearCancelledHook'> </transition>
10、(1)多个元素的过渡(使用key)
<transition> <button :key="docState"> {{ buttonMessage }} </button> </transition> computed: { buttonMessage: function () { switch (this.docState) { case 'saved': return '编辑' case 'edited': return '保存' case 'editing': return '取消' } } } 过渡模式 out-in 当前元素先进行过渡,完成之后新元素过渡进入 in-out 新元素先进行过渡,完成之后当前元素过渡离开 <transition name="fade" mode="out-in"> </transition>
10、(2)多个组件的过渡(使用动态组件)
<transition name="component-fade" mode="out-in"> <component v-bind:is="view"></component> </transition> new Vue({ el:'demo', data:{ view:'v-a' }, components:{ 'v-a':{ template:`<div>组件A</div>` }, 'v-b':{ template:`<div>组件B</div>` } } }) .component-fade-enter-active, .component-fade-leave-active { transition: opacity .3s ease; } .component-fade-enter, .component-fade-leave-to { opacity: 0; }
11、<transition-group> 组件实现列表的过渡
<transition-group>组件会渲染成<span>标签,可通过 tag 特性更换为其他元素。 目标元素必须提供唯一的 key 值 <div id='demo'> <button @click='add'>添加</button> <button @click='remove'>删除</button> <button @click='shuffle'>打乱</button> <transition-group name='list' tag='div'> <span v-for='item in items' :key='item' class='list-item'> {{item}} </span> </transition-group> </div> //_.shuffl(arr) 随机打乱数组,并返回被打乱的数组 //arr.splice(index,0,item) 在index位置添加一个 item 元素 //arr.splice(index,1) 在index位置删除1个元素 new Vue({ el:'demo', data:{ items:[1,2,3,4,5,6,7,8,9], nextNum:10 }, methods:{ randomIndex:function(){ //返回1~9之间的随机数 return Math.floor(Math.random()*this.items.length) }, add:function(){ this.items.splice(this.randomIndex,0,nextNum++); //在随机的位置添加一个数 }, remove:function(){ this.items.splice(this.randomIndex,1); //在随机的位置删除一个数 }, shuffle:function(){ this.items=_.shuffle(this.items); //返回顺序被打乱的数组 } } }) .list-item{ transition:all 1s; display:inline-block; margin-right:10px; } .list-leave-active { position: absolute; } .list-enter, .list-leave-to { opacity: 0; transform: translateY(30px); }
12、与JavaScript交互实现交错过渡(Velocity.js)
<div id='demo'> <input v-model='query'> //根据用户输入筛选显示列表中符合项+动画 <transition-group name='fade' tag='ul' :css='false' @before-enter='beforeEnter' @enter='enter' @leave='leave'> <li v-for='(item,index) in items' :key='item.msg' :data-index='index'> {{item.msg}} </li> </transition-group> </div> new Vue({ el:'#demo', data:{ query:'', list:[ {msg:'then'}, {msg:'reject'}, {msg:'undefiend'}, {msg:'resolve'} ] }, computed:{ showList:function(){ var vm=this; return this.list.filter(function(item){ return item.msg.toLowerCase().indexOf(vm.query.toLowerCase()) !==-1 }) } }, methods:{ beforeEnter:function(el){ el.style.opacity=0; el.style.height=0; }, enter:function(el,done){ var delay=el.dataset.index*150; setTimeout(function(){ Velocity( el, { opacity: 1, height: '1.6em' }, { complete: done } ) }, delay) }, leave:function(el,done){ var delay = el.dataset.index * 150 setTimeout(function () { Velocity( el, { opacity: 0, height: 0 }, { complete: done } ) }, delay) } } })