
本文共 10399 字,大约阅读时间需要 34 分钟。
单元素过渡
一、单元素过渡
Vue 在插入、更新或者移除 DOM 时,提供多种不同方式的应用过渡效果。
1.单元素/组件的过渡
Vue 提供了 transition 的封装组件,在下列情形中,可以给任何元素和组件添加进入/离开过渡
- 条件渲染 (使用 v-if)
- 条件展示 (使用 v-show)
- 动态组件
- 组件根节点
2.过渡的类名
在进入/离开的过渡中,会有 6 个 class 切换。
1. v-enter:
定义进入过渡的开始状态。
在元素被插入之前生效,在元素被插入之后的下一帧移除。
2. v-enter-active:
定义进入过渡生效时的状态。
在整个进入过渡的阶段中应用,在元素被插入之前生效,在过渡/动画完成之后移除。
这个类可以被用来定义进入过渡的过程时间,延迟和曲线函数。
3. v-enter-to:
定义进入过渡的结束状态(2.1.8+) 。
在元素被插入之后下一帧生效 (与此同时 v-enter 被移除),在过渡/动画完成之后移除。
4. v-leave:
定义离开过渡的开始状态。
在离开过渡被触发时立刻生效,下一帧被移除。
5. v-leave-active:
定义离开过渡生效时的状态。
在整个离开过渡的阶段中应用,在离开过渡被触发时立刻生效,在过渡/动画完成之后移除。
这个类可以被用来定义离开过渡的过程时间,延迟和曲线函数。
5. v-leave-to:
定义离开过渡的结束状态(2.1.8+) 。
在离开过渡被触发之后下一帧生效 (与此同时 v-leave 被删除),在过渡/动画完成之后移除。
<template> <div class="demo"> <button @click="show = !show">click</button> <transition> <div class="box" v-show="show">hellow world</div> </transition> </div></template><script>export default { data(){ return { show: true } }}</script><style scoped>button { margin-bottom: 10px;}.box { width: 100px; height: 100px; line-height: 100px; text-align: center; border: 1px solid red; color: red;}.v-enter { opacity: 0; transform: translateX(250px);}.v-enter-active { transition: all 0.8s;}.v-enter-to { opacity: 1; transform: translateX(0px);}.v-leave { opacity: 1; transform: translateX(0px);}.v-leave-active { transition: all 0.8s;}.v-leave-to { opacity: 0; transform: translateX(250px);}</style>
3.类名前缀
- transition 无 name 特性
类名前缀为 v-。
.v-enter { opacity: 0; transform: translateX(250px);}.v-enter-active { transition: all 0.8s;}.v-enter-to { opacity: 1; transform: translateX(0px);}.v-leave { opacity: 1; transform: translateX(0px);}.v-leave-active { transition: all 0.8s;}.v-leave-to { opacity: 0; transform: translateX(250px);}
- transition 有 name 特性
如 name 为 fade,则类名前缀为fade-。
<template> <div class="demo"> <button @click="show = !show">click</button> <transition name="box1"> <div class="box" v-if="show">hello world</div> </transition> <transition name="box2"> <div class="box" v-if="show">hello world</div> </transition> </div></template><script>export default { data () { return { show: true, } }}</script><style scoped>button { margin-bottom: 10px;}.box { width: 100px; height: 100px; margin-bottom: 10px; line-height: 100px; text-align: center; border: 1px solid red; color: red;}/* 合并代码,减少耦合和代码量 */.box1-enter,.box1-leave-to { opacity: 0; transform: translateX(200px);}.box1-enter-active,.box1-leave-active { transition: all .3s;}.box1-enter-to,.box1-leave { opacity: 1; transform: translateX(0px);}.box2-enter-to,.box2-leave { opacity: 1; transform: translateY(0px);}.box2-enter-active,.box2-leave-active { transition: all .3s;}.box2-enter,.box2-leave-to { opacity: 0; transform: translateY(200px);}</style>
4.CSS 动画
CSS 动画用法同 CSS 过渡,区别是在动画中 v-enter 类名在节点插入 DOM 后不会立即删除,而是在 animationend 事件触发时删除。
<template> <div class="demo"> <button @click="show = !show">click</button> <transition> <div class="box" v-if="show">hello world</div> </transition> </div></template><script>export default { data () { return { show: true, } }}</script><style scoped>button { margin-bottom: 10px;}.box { width: 100px; height: 100px; margin-bottom: 10px; line-height: 100px; text-align: center; border: 1px solid red; color: red;}.v-enter-active { animation: animate 1s;}.v-leave-active { animation: animate 1s reverse;}@keyframes animate { 0% { opacity: 0; transform: translateX(400px) scale(1); } 50% { opacity: .5; transform: translateX(200px) scale(1.5); } 100% { opacity: 1; transform: translateX(0) scale(1); }}</style>
5.自定义过渡的类名
我们可以通过以下 attribute 来自定义过渡类名:
- enter-class
- enter-active-class
- enter-to-class (2.1.8+)
- leave-class
- leave-active-class
- leave-to-class (2.1.8+)
<template> <div class="demo"> <button @click="show = !show">click</button> <transition enter-active-class="enter" leave-active-class="leave"> <div class="box" v-if="show">hello world</div> </transition> </div></template><script>export default { data () { return { show: true, } }}</script><style scoped>button { margin-bottom: 10px;}.box { width: 100px; height: 100px; margin-bottom: 10px; line-height: 100px; text-align: center; border: 1px solid red; color: red;}.enter { animation: animate 1s;}.leave { animation: animate 1s reverse;}@keyframes animate { 0% { opacity: 0; transform: translateX(400px) scale(1); } 50% { opacity: .5; transform: translateX(200px) scale(1.5); } 100% { opacity: 1; transform: translateX(0) scale(1); }}</style>
他们的优先级高于普通的类名,这对于 Vue 的过渡系统和其他第三方 CSS 动画库(如 Animate.css)结合使用十分有用。
由于我们不会愿意花太多时间去写一个好的动画,那么通过命名就能对各样动画进行命名。
下面推荐一款动画的css
Animate.css 官网地址:https://daneden.github.io/animate.css/
安装方式:npm install animate.css --save
,最后引入css
<template> <div class="demo"> <button @click="show = !show">click</button> <transition enter-active-class="animated bounceInRight" leave-active-class="animated bounceOutDown"> <div class="box" v-if="show">hello world</div> </transition> </div></template>
6.同时使用过渡和动画
可使用 type 属性,来声明需要 Vue 监听的类型,type值可为 animation 或 transition 。
当不设置type时,默认会取 transitioned 和 animationed 两者更长的为结束时刻。(以哪个为主)
<template> <div class="demo"> <button @click="show = !show">click</button> <transition type="animation" enter-active-class="animated tada v-enter-active" leave-active-class="animated tada v-leave-active" > <div class="box" v-if="show">hello world</div> </transition> </div></template><script>export default { data () { return { show: true, } }}</script><style scoped>button { margin-bottom: 10px;}.box { width: 100px; height: 100px; margin-bottom: 10px; line-height: 100px; text-align: center; border: 1px solid red; color: red;}.v-enter,.v-leave-to { opacity: 0;}.v-enter-active,.v-leave-active { transition: all 5s;}.v-enter-to,.v-leave { opacity: 1;}</style>
7.显性的过渡时间
在一些情况下,Vue可以自动得出过渡效果的完成时机,从而对dom进行处理。
但是有些时候,我们会设置一系列的过渡效果,例如嵌套元素也有过渡动效,其过渡效果的时间长于父元素。此时我们可以设置duration属性,定制一个显性的过渡持续时间(以毫秒记):
<transition :duration="1000">...</transition><transition :duration="{ enter:400,leave:600 }">...</transition>
也可以定制进入和移出的持续时间:
<transition :duration="{ enter: 500, leave: 800 }">...</transition>
8.初始渲染的过渡
可以通过 appear
attribute 设置节点在初始渲染的过渡。
和进入/离开过渡一样,同样也可以自定义 CSS 类名。如:
appear-class="appear-enter"appear-active-class="appear-enter-active"appear-to-class="appear-enter-to"<template> <div class="demo"> <button @click="show = !show">click</button> <transition :duration="1000" appear //进入就显示 appear-active-class="animated swing" enter-active-class="animated tada" leave-active-class="animated tada" > <div class="box" v-if="show">hello world</div> </transition> </div></template>
9.JavaScript 钩子
可以在属性中声明 JavaScript 钩子:
<transition @before-enter="beforeEnter" //入场前 @enter="enter" //中 @after-enter="afterEnter" //后 @enter-cancelled="enterCancelled" //取消,用的很少 @before-leave="beforeLeave" @leave="leave" @after-leave="afterLeave" @leave-cancelled="leaveCancelled"> <!-- ... --></transition>
<template> <div class="demo"> <button @click="show = !show">click</button> <transition :css="false" @before-enter="beforeEnter" @enter="enter" @after-enter="afterEnter" @enter-cancelled="enterCancelled" > <div class="box" v-if="show">hello world</div> </transition> </div></template><script>export default { data () { return { show: true, x: 200, } }, methods: { beforeEnter (el) { el.style.transform = 'translateX(200px)'; }, enter (el, done) { //done.canceled = true;//一旦动画取消,就会执行enterCancelled函数 const timer = setInterval(() => { this.x -= 2; el.style.transform = `translateX(${ this.x}px)`; if(this.x <= 0) { clearInterval(timer); done();//done不执行,after就不会执行 } }, 10) }, afterEnter () { this.x = 200; }, enterCancelled: function () { // console.log('cancel'); // this.isCancel = true; } }}</script><style scoped>button { margin-bottom: 10px;}.box { width: 100px; height: 100px; margin-bottom: 10px; line-height: 100px; text-align: center; border: 1px solid red; color: red;}</style>
- before-enter 动画入场前,可以在其中设置元素开始动画之前的起始样式
- enter 动画入场中,可以在其中写动画
- after-enter 动画完成后
- enter-cancelled 取消动画
对于仅使用 JavaScript 过渡的元素添加 v-bind:css=“false”,Vue 会跳过 CSS 的检测。这也可以避免过渡过程中 CSS 的影响。
设置了 appear 特性的 transition 组件,也存在自定义 JavaScript 钩子:
<transition appear v-on:before-appear="customBeforeAppearHook" v-on:appear="customAppearHook" v-on:after-appear="customAfterAppearHook" v-on:appear-cancelled="customAppearCancelledHook"> <!-- ... --></transition>
结合 Velocity.js
继续懒,所以有了js的动画插件
Velocity.js 官网地址:http://velocityjs.org/
安装方式:npm install velocity-animate
<template> <div class="demo"> <button @click="show = !show">click</button> <transition :css="false" @before-enter="beforeEnter" @enter="enter" @before-leave="beforeLeave" @leave="leave" > <div class="box" v-if="show">hello world</div> </transition> </div></template><script>export default { data () { return { show: true, } }, methods: { beforeEnter (el) { el.style.opacity = 0; }, enter (el, done) { Velocity(el, { opacity: 1}, { duration: 500}); Velocity(el, { rotateZ: 10 }, { duration: 300 }); Velocity(el, { rotateZ: -10 }, { duration: 300 }); Velocity(el, { rotateZ: 0 }, { duration: 300, complete: done }); }, beforeLeave (el) { el.style.transformOrigin = 'left'; }, leave (el, done) { Velocity(el, { translateX: '15px', rotateZ: '50deg'}, { duration: 600}); Velocity(el, { rotateZ: '100deg'}, { duration: 600, loop: 2}); Velocity(el, { rotateZ: '45deg', translateY: '30px', translateX: '30px', opacity: 0}, { complete: done}); }, }}</script><style scoped>button { margin-bottom: 10px;}.box { width: 200px; margin-bottom: 10px; text-align: center; border: 1px solid red; color: red;}</style>
发表评论
最新留言
关于作者
