聊一聊Vue.js过渡效果


Posted in Javascript onSeptember 07, 2016

通过 Vue.js 的过渡系统,你可以轻松的为 DOM 节点被插入/移除的过程添加过渡动画效果。Vue 将会在适当的时机添加/移除 CSS 类名来触发 CSS3 过渡/动画效果,你也可以提供相应的 JavaScript 钩子函数在过渡过程中执行自定义的 DOM 操作。

v-transition="my-transition" 这个指令为例,当带有这个指令的 DOM 节点被插入或移除时,Vue 将会:

my-transition 这个 ID 去查找是否有注册过的 JavaScript 钩子对象。这个对象可以是由 Vue.transition(id, hooks) 全局注册,或是通过 transitions 选项定义在当前的组件内部。如果找到此对象,则会在过渡动画不同的阶段调用相应的钩子。

自动探测目标元素是否应用了 CSS 过渡效果或者动画效果,并在适当的时机添加/移除 CSS 类名。

如果没有提供 JavaScript 钩子函数,也没有检测到相应的 CSS 过渡/动画效果,DOM 的插入/移除会在下一帧立即执行。
所有的 Vue.js 过渡效果只有在该 DOM 操作是通过 Vue.js 触发时才会生效。触发的方式可以是通过内置指令,比如 v-if,或是通过 Vue 实例的方法,比如 vm.$appendTo()。

CSS 过渡效果
一个典型的 CSS 过渡效果定义如下:

<div v-if="show" v-transition="expand">hello</div>

你还需要定义 .expand-transition, .expand-enter 和.expand-leave 三个 CSS 类:

.expand-transition {
 transition: all .3s ease;
 height: 30px;
 padding: 10px;
 background-color: #eee;
 overflow: hidden;
}
.expand-enter, .expand-leave {
 height: 0;
 padding: 0 10px;
 opacity: 0;
}

同时,你也可以提供 JavaScript 钩子:

Vue.transition('expand', {
 beforeEnter: function (el) {
  el.textContent = 'beforeEnter'
 },
 enter: function (el) {
  el.textContent = 'enter'
 },
 afterEnter: function (el) {
  el.textContent = 'afterEnter'
 },
 enterCancelled: function (el) {
  // handle cancellation
 },
`
 beforeLeave: function (el) {
  el.textContent = 'beforeLeave'
 },
 leave: function (el) {
  el.textContent = 'leave'
 },
 afterLeave: function (el) {
  el.textContent = 'afterLeave'
 },
 leaveCancelled: function (el) {
  // handle cancellation
 }
})

结果

聊一聊Vue.js过渡效果

这里使用的 CSS 类名由 v-transition 指令的值所决定。以 v-transition="fade" 为例,CSS 类 .fade-transition 将会一直存在,而 .fade-enter 和 .fade-leave 将会在合适的时机自动被添加或移除。当 v-transition 指令没有提供值的时候,所使用的 CSS 类名将会是默认的 .v-transition, .v-enter 和 .v-leave。

当 show 属性变化时,Vue 会依据其当前的值来插入/移除 <div> 元素,并在合适的时机添加/移除对应的 CSS 类,具体如下:

当 show 变为 false 时,Vue 将会:

1.调用 beforeLeave 钩子;
2.在元素上应用 CSS 类 .v-leave 来触发过渡效果;
3.调用 leave 钩子;
4.等待过渡效果执行完毕; (监听 transitionend 事件)
5.从 DOM 中移除元素并且移除 CSS 类 .v-leave。
6.调用 afterLeave 钩子。

当 show 为 true 时,Vue 将会:

1.调用 beforeEnter 钩子;
2.在元素上应用 CSS 类 .v-enter;
3.将元素插入 DOM;
4.调用 enter 钩子;
5.应用 .v-enter 类, 然后强制 CSS 布局以保证 .v-enter 生效;最后移除 .v-enter 来触发元素过渡到原本的状态。
6.等待过渡效果执行完毕;
7.调用 afterEnter 钩子。

此外,如果一个正在执行进入的过渡效果的元素在过渡还未完成之前就被移除,则 enterCancelled 钩子将会被执行。这个钩子可以用于清理工作,比如移除在 enter 时创建的计时器。对于正在离开过渡中又被重新插入的元素同理。

上述所有的钩子函数执行时,其 this 都指向相应的 Vue 实例。如果一个元素本身是一个 Vue 实例的根节点,则此实例将被应用为 this;否则 this 指向该过渡指令所属的实例。

最后,enter 与 leave 钩子函数可以接受可选的第二个参数:一个回调函数。当你的函数签名中含有第二个参数时,即表示你期望使用此回调来显式地完成整个过渡过程,而不是依赖 Vue 去自动检测 CSS 过渡的 transitionend 事件。比如:

enter: function (el) {
 // 无第二个参数
 // 过渡效果的结束由 CSS 过渡结束事件来决定
}

VS

enter: function (el, done) {
 // 有第二个参数
 // 过渡效果结束必须由手动调用 `done` 来决定
}

当多个元素同时执行过渡效果时,Vue.js 会进行批量处理以保证只触发一次强制布局。

CSS 动画
CSS 动画通过与 CSS 过渡效果一样的方式进行调用,区别就是动画中 .v-enter 类并不会在节点插入 DOM 后马上移除,而是在 animationend 事件触发时移除。

示例: (省略了兼容性前缀)

<span v-show="show" v-transition="bounce">Look at me!</span>

.bounce-enter {
 animation: bounce-in .5s;
}
.bounce-leave {
 animation: bounce-out .5s;
}
@keyframes bounce-in {
 0% {
  transform: scale(0);
 }
 50% {
  transform: scale(1.5);
 }
 100% {
  transform: scale(1);
 }
}
@keyframes bounce-out {
 0% {
  transform: scale(1);
 }
 50% {
  transform: scale(1.5);
 }
 100% {
  transform: scale(0);
 }
}

结果

聊一聊Vue.js过渡效果

纯 JavaScript 过渡效果
你也可以只使用 JavaScript 钩子,不定义任何 CSS 过渡规则。当只使用 JavaScript 钩子时,enter 和 leave 钩子必须使用 done 回调,否则它们将会被同步调用,过渡将立即结束。下面的示例中我们使用 jQuery 来注册一个自定义的 JavaScript 过渡效果:

Vue.transition('fade', {
 enter: function (el, done) {
  // 此时元素已被插入 DOM
  // 动画完成时调用 done 回调
  $(el)
   .css('opacity', 0)
   .animate({ opacity: 1 }, 1000, done)
 },
 enterCancelled: function (el) {
  $(el).stop()
 },
 leave: function (el, done) {
  // 与 enter 钩子同理
  $(el).animate({ opacity: 0 }, 1000, done)
 },
 leaveCancelled: function (el) {
  $(el).stop()
 }
})

定义此过渡之后,你就可以通过给 v-transition 指定对应的 ID 来调用它:

<p v-transition="fade"></p>

如果一个只使用 JavaScript 过渡效果的元素恰巧也受到其它 CSS 过渡/动画规则的影响,这可能会对 Vue 的 CSS 过渡检测机制产生干扰。碰到这样的状况时,你可以通过给你的钩子对象添加 css: false 来禁止 CSS 检测。

渐进过渡效果
当同时使用 v-transition 和 v-repeat 时,我们可以为列表元素添加渐进的过渡效果,你只需要为你的过渡元素加上 stagger, enter-stagger 或者 leave-stagger 特性(以毫秒为单位):

<div v-repeat="list" v-transition stagger="100"></div>

或者你也可以提供 stagger, enterStagger 或 eaveStagger 钩子来进行更细粒度的控制:

Vue.transition('stagger', {
 stagger: function (index) {
  // 为每个过渡元素增加 50ms 的延迟,
  // 但是最大延迟为 300ms
  return Math.min(300, index * 50)
 }
})

示例:

聊一聊Vue.js过渡效果

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
jquery 获取表单元素里面的值示例代码
Jul 28 Javascript
Json和Jsonp理论实例代码详解
Nov 15 Javascript
JS获取几种URL地址的方法小结
Feb 26 Javascript
AngularJS初始化静态模板详解
Jan 14 Javascript
原生javascript实现解析XML文档与字符串
Mar 01 Javascript
Vue.js父与子组件之间传参示例
Feb 28 Javascript
Javascript创建类和对象详解
May 31 Javascript
webstorm添加vue.js支持的方法教程
Jul 05 Javascript
BootStrap 页签切换失效的解决方法
Aug 17 Javascript
Vue中建立全局引用或者全局命令的方法
Aug 21 Javascript
深入理解Vue生命周期、手动挂载及挂载子组件
Sep 27 Javascript
浅谈layui框架自带分页和表格重载的接口解析问题
Sep 11 Javascript
BootStrap中的表单大全
Sep 07 #Javascript
JS实现title标题栏文字不间断滚动显示效果
Sep 07 #Javascript
JavaScript 函数模式详解及示例
Sep 07 #Javascript
jquery 属性选择器(匹配具有指定属性的元素)
Sep 06 #Javascript
jquery validate表单验证插件
Sep 06 #Javascript
HTML5 canvas 9绘制图片实例详解
Sep 06 #Javascript
js 获取元素所有兄弟节点的实现方法
Sep 06 #Javascript
You might like
PHP自定义函数实现数组比较功能示例
2017/10/19 PHP
PhpStorm连接服务器并实现自动上传功能
2020/12/09 PHP
求得div 下 img的src地址的js代码
2007/02/28 Javascript
jQuery 使用手册(六)
2009/09/23 Javascript
(跨浏览器基础事件/浏览器检测/判断浏览器)经验代码分享
2013/01/24 Javascript
js超时调用setTimeout和间歇调用setInterval实例分析
2015/01/28 Javascript
JS+CSS实现简单的二级下拉导航菜单效果
2015/09/21 Javascript
javascript实现别踩白块儿小游戏程序
2015/11/22 Javascript
让微信小程序支持ES6中Promise特性的方法详解
2017/06/13 Javascript
vue.js项目中实用的小技巧汇总
2017/11/29 Javascript
JavaScript中字符串的常用操作方法及特殊字符
2018/03/18 Javascript
nodejs读取并去重excel文件
2018/04/22 NodeJs
20个最常见的jQuery面试问题及答案
2018/05/23 jQuery
关于AngularJS中ng-repeat不更新视图的解决方法
2018/09/30 Javascript
为什么要使用Vuex的介绍
2019/01/19 Javascript
微信小程序template模板与component组件的区别和使用详解
2019/05/22 Javascript
了解在JavaScript中将值转换为字符串的5种方法
2019/06/06 Javascript
JS实现动态无缝轮播
2020/01/11 Javascript
详解在Vue.js编写更好的v-for循环的6种技巧
2020/04/14 Javascript
ajax jquery实现页面某一个div的刷新效果
2021/03/04 jQuery
如何将python中的List转化成dictionary
2016/08/15 Python
python利用不到一百行代码实现一个小siri
2017/03/02 Python
python字符串str和字节数组相互转化方法
2017/03/18 Python
Python向日志输出中添加上下文信息
2017/05/24 Python
树莓派用python中的OpenCV输出USB摄像头画面
2019/06/22 Python
学python需要去培训机构吗
2020/07/01 Python
pandas实现导出数据的四种方式
2020/12/13 Python
css3 按钮 利用css3实现超酷下载按钮
2013/03/18 HTML / CSS
使用phonegap获取位置信息的实现方法
2017/03/31 HTML / CSS
Rhone官方网站:男士运动服装、健身服装和高级运动服
2019/05/01 全球购物
Chi Chi London官网:购买连衣裙和礼服
2020/10/25 全球购物
美国购买隐形眼镜网站:Lenses For Less
2020/07/05 全球购物
经贸日语毕业生自荐信
2013/11/03 职场文书
土地转让协议书
2014/09/27 职场文书
认识实习感想
2015/08/10 职场文书
剑指Offer之Java算法习题精讲二叉树的构造和遍历
2022/03/21 Java/Android