聊一聊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 相关文章推荐
解决FireFox下[使用event很麻烦]的问题
Nov 26 Javascript
js实现简单模态窗口,背景灰显
Nov 14 Javascript
让textarea自动调整大小的js代码
Apr 12 Javascript
jquery插件ajaxupload实现文件上传操作
Dec 09 Javascript
javascript结合Flexbox简单实现滑动拼图游戏
Feb 18 Javascript
个人网站留言页面(前端jQuery编写、后台php读写MySQL)
May 03 Javascript
让浏览器崩溃的12行JS代码(DoS攻击分析及防御)
Oct 10 Javascript
关于iframe跨域POST提交的方法示例
Jan 15 Javascript
Javascript下拉刷新的简单实现
Feb 14 Javascript
js实现简单的获取验证码按钮效果
Mar 03 Javascript
JS实现处理时间,年月日,星期的公共方法示例
May 31 Javascript
使用JS监听键盘按下事件(keydown event)
Nov 07 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
国王的咖啡这么大来头,名字的由来是什么
2021/03/03 咖啡文化
在PHP中使用模板的方法
2008/05/24 PHP
php检测数组长度函数sizeof与count用法
2014/11/17 PHP
PHP中使用curl伪造IP的简单方法
2015/08/07 PHP
使用PHP实现生成HTML静态页面
2015/11/18 PHP
PHP设计模式之策略模式原理与用法实例分析
2019/04/04 PHP
js导出table到excel同时兼容FF和IE示例
2013/09/03 Javascript
Jquery给基本控件的取值、赋值示例
2014/05/23 Javascript
详解JavaScript数组和字符串中去除重复值的方法
2016/03/07 Javascript
JavaScript中的ParseInt(&quot;08&quot;)和“09”返回0的原因分析及解决办法
2016/05/19 Javascript
详解JavaScript中双等号引起的隐性类型转换
2016/05/30 Javascript
AngularJS基础 ng-init 指令简单示例
2016/08/02 Javascript
javascript 判断用户有没有操作页面
2017/10/17 Javascript
Javascript防止图片拉伸的自适应处理方法
2017/12/26 Javascript
JavaScript对象的浅拷贝与深拷贝实例分析
2018/07/25 Javascript
VUE-Table上绑定Input通过render实现双向绑定数据的示例
2018/08/27 Javascript
jQuery实现移动端图片上传预览组件的方法分析
2020/05/01 jQuery
OpenLayers3实现地图显示功能
2020/09/25 Javascript
用Python写的图片蜘蛛人代码
2012/08/27 Python
Python中AND、OR的一个使用小技巧
2015/02/18 Python
Python实现两个list求交集,并集,差集的方法示例
2018/08/02 Python
python3+requests接口自动化session操作方法
2018/10/13 Python
Django Rest framework之认证的实现代码
2018/12/17 Python
解决PyCharm不运行脚本,而是运行单元测试的问题
2019/01/17 Python
Python 如何提高元组的可读性
2019/08/26 Python
基于python实现matlab filter函数过程详解
2020/06/08 Python
Python 使用生成器代替线程的方法
2020/08/04 Python
CSS3实现红包抖动效果
2020/12/23 HTML / CSS
英国领先的电动可调床制造商:Laybrook
2019/12/26 全球购物
大学生新闻专业个人自我评价
2013/11/12 职场文书
运动会入场解说词300字
2014/01/25 职场文书
党的群众路线教育实践活动心得体会
2014/03/03 职场文书
铅球加油稿100字
2014/09/26 职场文书
小学教师求职信范文
2015/03/20 职场文书
python-for x in range的用法(注意要点、细节)
2021/05/10 Python
深入理解margin塌陷和margin合并的解决方案
2021/06/26 HTML / CSS