阅读目录
- 1.理解VUE---过渡效果
1.理解VUE---过渡效果
1. 过渡的-css-类名
会有4个(css) 类名在 enter/leave 在过渡中切换。
1. v-enter: 进入过渡的开始状态。在元素被插入时生效,在下一个帧移除。
2. v-enter-active: 进入过渡的结束状态。在元素被插入时生效,在 transition/animation 完成之后移除。
3. v-leave 离开过渡的开始状态。在离开过渡被触发时生效,在下一个帧移除。
4. v-leave-active 离开过渡的结束状态。在离开过渡被触发时生效,在 transition/animation 完成之后移除。
看如下图所示:
在enter/leave 过渡中切换的类名,v- 是类名的前缀,使用 <transition name="my-transition"> 可以重置前缀,比如 v-enter 替换为 my-transition-enter。
看如下demo
<!DOCTYPE html> <html><head><title>演示Vue</title><style>.fade-enter-active, .fade-leave-active {transition: opacity .5s}.fade-enter, .fade-leave-active {opacity: 0}</style></head><body><div id='app'><button v-on:click="show = !show">toggle</button><transition name='fade'><p v-if="show">hello</p></transition></div></body><script src="./vue.js"></script><script type="text/javascript">new Vue({el: '#app',data: {show: true}})</script> </html>
查看效果
如上代码; 给transition标签 定义了一个name属性,因此过渡的css类名中的前缀v被替换成fade,定义了 .fade-enter-active, .fade-leave-active {transition: opacity .5s } 过渡动画,定义进入过渡的结束状态和离开过渡的结束状态 为透明度0 在0.5s之内完成。
我们还可以定义如下的css,实现动画,如下css代码:
.fade-enter-active {transition: all .5s ease; } .fade-leave-active {transition: all .8s cubic-bezier(1.0, 0.5, 0.8, 1.0); } .fade-enter, .fade-leave-active {transform: translateX(10px);opacity: 0; }
查看效果
2. css动画
css动画用法同css过渡一样, 区别是在动画中 v-enter 类名在节点插入DOM后不会立即删除,而是在animationend事件触发时删除。如下代码也可以用在css动画下。
<!DOCTYPE html> <html><head><title>演示Vue</title><style>.fade-enter-active {animation: fade-in .5s;}.fade-leave-active {animation: fade-out .5s;}@keyframes fade-in {0% {transform: scale(0);}50% {transform: scale(1.5);}100% {transform: scale(1);}}@keyframes fade-out {0% {transform: scale(1);}50% {transform: scale(1.5);}100% {transform: scale(0);}}</style></head><body><div id='app'><button v-on:click="show = !show">toggle</button><transition name='fade'><p v-if="show">hello</p></transition></div></body><script src="./vue.js"></script><script type="text/javascript">new Vue({el: '#app',data: {show: true}})</script> </html>
查看效果
3. 自定义过渡类名
上面的四个过渡类名都是根据transition的name属性自动生成的,下面我们可以通过以下特性来自定义过渡类名。
enter-class
enter-active-class
leave-class
leave-active-class
以上的优先级都高于普通类名,通过以上的 我可以自定义类名写不同的样式了,如下代码:
如下使用的animate.css里面的样式实现动画:如下代码:
<!DOCTYPE html> <html><head><title>演示Vue</title><link href="https://unpkg.com/animate.css@3.5.1/animate.min.css" rel="stylesheet" type="text/css"></head><body><div id='app'><button v-on:click="show = !show">toggle</button><transitionname="custom-classes-transition"enter-active-class="animated tada"leave-active-class="animated bounceOutRight"><p v-if="show">hello</p></transition></div></body><script src="./vue.js"></script><script type="text/javascript">new Vue({el: '#app',data: {show: true}})</script> </html>
查看效果
4. 多个组件的过渡
多个组件的过渡可以使用动态组件实现,如下代码:
<!DOCTYPE html> <html><head><title>演示Vue</title><style>.component-fade-enter-active, .component-fade-leave-active {transition: opacity .3s ease;}.component-fade-enter, .component-fade-leave-active {opacity: 0;}</style></head><body><div id='app'><input v-model='view' type='radio' value='v-a' name="view" /><label for='a'>A</label><input v-model='view' type='radio' value='v-b' name='view' /><label for='b'>B</label><transition name='component-fade' mode='out-in'><component v-bind:is='view'></component></transition></div></body><script src="./vue.js"></script><script type="text/javascript">new Vue({el: '#app',data: {view: 'v-a'},components: {'v-a': {template: '<div>Component A</div>'},'v-b': {template: '<div>Component B</div>'}}})</script> </html>
查看效果
5. javascript钩子函数
除了使用css过渡的动画来实现vue的组件过渡,还可以使用javascript钩子函数来实现。在钩子函数中直接操作dom。我们在属性中声明如下钩子。
代码如下:
<transitionv-on:before-enter='beforeEnter'v-on:enter='enter'v-on:after-enter='afterEnter'v-on:enter-cancelled='enterCancelled'v-on:before-leave='beforeLeave'v-on:leave='leave'v-on:after-leave='afterLeave'v-on:leave-cancelled='leaveCancelled' > </transition> new Vue({el: '#app',data: {view: 'v-a'},methods: {// 过渡进入 设置过渡进入之前的组件状态beforeEnter: function(el) {},// 设置过渡进入完成时的组件状态enter: function(el, done) {// done()},// 设置过渡进入完成之后的组件状态afterEnter: function(el) {// .... },enterCancelled: function(el) {// ... },// 过渡离开 设置过渡离开之前的组件状态beforeLeave: function(el) {// 。。。。 },// 设置过渡离开完成时的组件状态leave: function(el, done) {// ... done()},// 设置过渡离开完成之后的组件状态afterLeave: function(el) {// ...... },leaveCancelled: function(el) {// .... }} })
注意:
1. 只用 JavaScript 过渡的时候, 在 enter 和 leave 中,回调函数 done 是必须的 。 否则,它们会被同步调用,过渡会立即完成。
2. 推荐对于仅使用 JavaScript 过渡的元素添加 v-bind:css="false",Vue 会跳过 CSS 的检测。这也可以避免过渡过程中 CSS 的影响。
下面是vue教程上Velocity.js的一个demo,如下代码:
<!DOCTYPE html> <html><head><title>演示Vue</title><style></style></head><body><div id='app'><button @click="show=!show">toggle</button><transitionv-on:before-enter='beforeEnter'v-on:enter='enter'v-on:leave='leave'v-bind:css='false'><p v-if='show'>Demo</p></transition></div></body><script src="./vue.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/velocity/1.2.3/velocity.js"></script><script type="text/javascript">new Vue({el: '#app',data: {show: true},methods: {// 过渡进入 设置过渡进入之前的组件状态 beforeEnter: function(el) {el.style.opacity = 0el.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 })}}})</script> </html>
查看效果
理解过渡模式:
如下demo
<!DOCTYPE html> <html><head><title>演示Vue</title><style>.no-mode-fade-enter-active, .no-mode-fade-leave-active {transition: opacity .5s}.no-mode-fade-enter, .no-mode-fade-leave-active {opacity: 0;}</style></head><body><div id='app'><transition name='no-mode-fade'><button v-if='on' key='on' @click='on=false'>on</button><button v-else='' key='off' @click='on=true'>off</button></transition></div></body><script src="./vue.js"></script><script type="text/javascript">new Vue({el: '#app',data: {on: false}})</script> </html>
查看效果
运行一下,在上面的on按钮 和 off按钮的过渡中,两个按钮都被重绘了,一个离开过渡的时候另一个开始进入过渡。这是 <transition> 的默认行为 - 进入和离开同时发生。
但是我们在元素绝对定位在彼此之上的时候运行正常:如下代码:
<!DOCTYPE html> <html><head><title>演示Vue</title><style>.wrap {position: relative;height: 18px;}.wrap button {position: absolute;}.no-mode-fade-enter-active, .no-mode-fade-leave-active {transition: opacity .5s}.no-mode-fade-enter, .no-mode-fade-leave-active {opacity: 0;}</style></head><body><div id='app'><div class='wrap'><transition name='no-mode-fade'><button v-if='on' key='on' @click='on=false'>on</button><button v-else='' key='off' @click='on=true'>off</button></transition></div></div></body><script src="./vue.js"></script><script type="text/javascript">new Vue({el: '#app',data: {on: false}})</script> </html>
查看效果
我们加上 translate 让它们运动像滑动过渡:代码如下:
<!DOCTYPE html> <html><head><title>演示Vue</title><style>.wrap {position: relative;height: 18px;}.wrap button {position: absolute;}.no-mode-fade-enter-active, .no-mode-fade-leave-active {transition: all 1s}.no-mode-fade-enter, .no-mode-fade-leave-active {opacity: 0;}.no-mode-fade-enter {transform: translateX(31px);}.no-mode-fade-leave-active {transform: translateX(-31px);}</style></head><body><div id='app'><div class='wrap'><transition name='no-mode-fade'><button v-if='on' key='on' @click='on=false'>on</button><button v-else='' key='off' @click='on=true'>off</button></transition></div></div></body><script src="./vue.js"></script><script type="text/javascript">new Vue({el: '#app',data: {on: false}})</script> </html>
查看效果
同时生效的进入和离开的过渡不能满足所有要求,所以 Vue 提供了 过渡模式
in-out: 新元素先进行过渡,完成之后当前元素过渡离开。
out-in: 当前元素先进行过渡,完成之后新元素过渡进入。
用 out-in 重写之前的开关按钮过渡:如下代码:
<!DOCTYPE html> <html><head><title>演示Vue</title><style>.no-mode-fade-enter-active, .no-mode-fade-leave-active {transition: opacity .5s}.no-mode-fade-enter, .no-mode-fade-leave-active {opacity: 0;}</style></head><body><div id='app'><div class='wrap'><transition name='no-mode-fade' mode='out-in'><button v-if='on' key='on' @click='on=false'>on</button><button v-else='' key='off' @click='on=true'>off</button></transition></div></div></body><script src="./vue.js"></script><script type="text/javascript">new Vue({el: '#app',data: {on: false}})</script> </html>
查看效果
in-out 滑动淡出demo如下:
<!DOCTYPE html> <html><head><title>演示Vue</title><style>.wrap {position: relative;height: 18px;}.wrap button {position: absolute;}.no-mode-fade-enter-active, .no-mode-fade-leave-active {transition: all .5s}.no-mode-fade-enter, .no-mode-fade-leave-active {opacity: 0;}.no-mode-fade-enter {transform: translateX(31px);}.no-mode-fade-leave-active {transform: translateX(-31px);}</style></head><body><div id='app'><div class='wrap'><transition name='no-mode-fade' mode='in-out'><button v-if='on' key='on' @click='on=false'>on</button><button v-else='' key='off' @click='on=true'>off</button></transition></div></div></body><script src="./vue.js"></script><script type="text/javascript">new Vue({el: '#app',data: {on: false}})</script> </html>
查看效果
5. VUE列表过渡实现轮播图
列表过渡使用 <transition-group> 组件,不同于 <transition>:
1. 它会以一个真实元素呈现:默认为一个 <span>。你也可以通过 tag 特性更换为其他元素。
2. 内部元素 总是需要 提供唯一的 key 属性值。
<!DOCTYPE html> <html><head><title>演示Vue</title><style>* { margin:0; padding:0;}.carousel-wrap {position: relative;height: 280px;width: 520px;overflow: hidden;// 删除background-color: #fff;}.slide-ul {width: 100%;height: 100%;}.slide-ul li {position: absolute;width: 100%;height: 100%;}.slide-ul li img {width: 100%;height: 100%;}.carousel-items {position: absolute;z-index: 10;bottom: 10px;width: 100%;margin: 0 auto;text-align: center;font-size: 0;}.carousel-items span {display: inline-block;height: 6px;width: 30px;margin: 0 3px;background-color: #b2b2b2;cursor: pointer;}.carousel-items span.active {background-color: red;}.list-enter-active {transition: all 1s ease;transform: translateX(0)}.list-leave-active {transition: all 1s ease;transform: translateX(-100%)}.list-enter {transform: translateX(100%)}.list-leave {transform: translateX(0)}</style></head><body><div id='carousel' class='carousel-wrap'><transition-group tag='ul' class='slide-ul' name='list'><li v-for='(list, index) in slideList' :key='index' v-show='index===currentIndex' @mouseenter='stop' @mouseleave='go'><a :href='list.href'><img :src='list.image' :alt='list.desc'></a></li></transition-group><div class='carousel-items'><span v-for="(item, index) in slideList.length" :class="{'active':index===currentIndex}" @mouseover="change(index)">{{index}}</span></div></div></body><script src="./vue.js"></script><script type="text/javascript">new Vue({el: '#carousel',data: {slideList: [{'href': '','desc': '1111','image': 'http://img.alicdn.com/tfs/TB1vHswQVXXXXXMXFXXXXXXXXXX-520-280.png_q90_.webp'},{'href': '','desc': '2222','image': 'http://img.alicdn.com/tfs/TB1c9kFQVXXXXcoXpXXXXXXXXXX-520-280.jpg_q90_.webp'},{'href': '','desc': '3333','image': 'https://aecpm.alicdn.com/tps/i1/TB1r4h8JXXXXXXoXXXXvKyzTVXX-520-280.jpg'}],currentIndex: 0,timer: ''},methods: {create: function() {var self = this;// DOM加载完成后,下个tick中开始轮播this.$nextTick(function(){self.timer = setInterval(function(){self.autoPlay();}, 4000)})},go: function() {var self = this;self.timer = setInterval(function(){self.autoPlay();},4000)},stop: function() {var self = this;clearInterval(self.timer);self.timer = null;},change: function(index) {this.currentIndex = index;},autoPlay: function() {this.currentIndex++;if(this.currentIndex > this.slideList.length - 1) {this.currentIndex = 0;}}}})</script> </html>
查看效果