聊一聊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 相关文章推荐
JavaScript的eval JSON object问题
Nov 15 Javascript
js textarea自动增高并隐藏滚动条
Dec 16 Javascript
javaScript checkbox 全选/反选及批量删除
Apr 28 Javascript
自定义jQuery插件方式实现强制对象重绘的方法
Mar 23 Javascript
详解js中Json的语法与格式
Nov 22 Javascript
JS正则表达式学习之贪婪和非贪婪模式实例总结
Dec 26 Javascript
浅谈让你的代码更简短,更整洁,更易读的ES6小技巧
Oct 25 Javascript
如何在项目中使用log4.js的方法步骤
Jul 16 Javascript
详解Vue中的Props与Data细微差别
Mar 02 Javascript
ES6 Generator基本使用方法示例
Jun 06 Javascript
js实现详情页放大镜效果
Oct 28 Javascript
解决Ant Design Modal内嵌Form表单initialValue值不动态更新问题
Oct 29 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获取时间排除周六、周日的两个方法
2014/06/30 PHP
PHP封装分页函数实现文本分页和数字分页
2014/10/23 PHP
thinkphp使用phpmailer发送邮件的方法
2014/11/24 PHP
PHP XML和数组互相转换详解
2016/10/26 PHP
PHP操作MongoDB实现增删改查功能【附php7操作MongoDB方法】
2018/04/24 PHP
JavaScript中json对象和string对象之间相互转化
2012/12/26 Javascript
判断js中各种数据的类型方法之typeof与0bject.prototype.toString讲解
2013/11/07 Javascript
jquery滚动加载数据的方法
2015/03/09 Javascript
JavaScript 变量、作用域及内存
2015/04/08 Javascript
readonly和disabled属性的区别
2015/07/26 Javascript
AngularJs bootstrap搭载前台框架——准备工作
2016/09/01 Javascript
js与jquery分别实现tab标签页功能的方法
2016/11/18 Javascript
AngularJS入门教程之路由机制ngRoute实例分析
2016/12/13 Javascript
利用原生的JavaScript实现简单拼图游戏
2018/11/18 Javascript
vue 右键菜单插件 简单、可扩展、样式自定义的右键菜单
2018/11/29 Javascript
用JS实现选项卡
2020/03/23 Javascript
JavaScript常用工具函数库汇总
2020/09/17 Javascript
安装python时MySQLdb报错的问题描述及解决方法
2018/03/20 Python
Python基于lxml模块解析html获取页面内所有叶子节点xpath路径功能示例
2018/05/16 Python
基于Pandas读取csv文件Error的总结
2018/06/15 Python
Python读取英文文件并记录每个单词出现次数后降序输出示例
2018/06/28 Python
Python3中在Anaconda环境下安装basemap包
2018/10/21 Python
Python 函数绘图及函数图像微分与积分
2019/11/20 Python
Python 内置变量和函数的查看及说明介绍
2019/12/25 Python
python产生模拟数据faker库的使用详解
2020/11/04 Python
一款利用纯css3实现的超炫3D表单的实例教程
2014/12/01 HTML / CSS
美国最大的农村生活方式零售店:Tractor Supply Company(TSC)
2017/05/15 全球购物
味多美官网:蛋糕订购,100%使用天然奶油
2017/11/10 全球购物
Java中有几种类型的流?JDK为每种类型的流提供了一些抽象类以供继承,请说出他们分别是哪些类?
2012/05/30 面试题
给护士表扬信
2014/01/19 职场文书
目标管理责任书
2014/04/15 职场文书
高中学生期末评语
2014/04/25 职场文书
学校教师读书活动总结
2014/07/08 职场文书
护林员个人总结
2015/03/04 职场文书
公司员工培训管理制度
2015/08/04 职场文书
Python中rapidjson参数校验实现
2021/07/25 Python