By
被删
更新日期:
最近在捣鼓 Vue 动画的内容,《Vue2 动画》系列用于记录一些使用方法、demo 以及原理分析。本文介绍使用 Javascript 钩子来实现动画效果的过程。
JavaScript 钩子
完整的钩子信息
这里我们直接贴出官网的展示:
1 2 3 4 5 6 7 8 9 10 11 12 13
| <transition v-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>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| 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) { } }
|
这里对进入和离开的动画钩子说明也比较清晰了,我们来看个 demo:
使用 jQuery 的例子
官方提供一个使用 Velocity.js 的例子,这块本骚年不熟悉,就直接拿个最简单的 jQuery 动画来写把~
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <div id="example-4"> <button @click="show = !show"> Toggle </button> <transition v-on:enter="enter" v-on:leave="leave" v-bind:css="false" > <p v-if="show"> Demo </p> </transition> </div>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| new Vue({ el: '#example-4', data: { show: false }, methods: { enter: (el, done) => { $(el) .css('opacity', 0) .animate({ opacity: 1, fontSize: '100px' }, 1000, done) }, leave: (el, done) => { $(el).animate({ opacity: 0, fontSize: '0px' }, 1000, done) } } })
|
可以看看这里的demo。
初始渲染
Vue 的动画提供了一个初始渲染的开关,指的是第一次展示(而不是第一次切换)的时候是否需要动画效果。
具体可以看看上面的例子,当我们把 show 的默认值设置为 true 的时候,初次展示并不会加载进入动画。
但是当我们在 transition 组件中添加 appear 属性时,则在初次展示时也会加载进入动画:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <div id="example-4"> <button @click="show = !show"> Toggle </button> <transition appear v-on:enter="enter" v-on:leave="leave" v-bind:css="false" > <p v-if="show"> Demo </p> </transition> </div>
|
可以查看demo,尝试将 appear 去掉试试(demo),看看区别就能理解了~
当然,你也可以绑定 appear 专属的动画效果:
1 2 3 4 5 6 7 8 9
| <transition appear v-on:before-appear="customBeforeAppearHook" v-on:appear="customAppearHook" v-on:after-appear="customAfterAppearHook" v-on:appear-cancelled="customAppearCancelledHook" > </transition>
|
实现逻辑
上一节《Vue2动画1–transition组件》中,我们详细描述了在使用 CSS 过渡和动画的时候,具体的实现原理。
而 Javascript 钩子的实现逻辑其实很简单:
- 检测组件是否使用了 Javascript 钩子。
- 若使用了 Javascript 钩子,则这些钩子函数将在恰当的时机被调用。
当然这些钩子分别穿插在各个地方,顺序的话也很明了。这里以离开动画为例子,我们来看看这段被我简化后的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
| export function leave (vnode: VNodeWithData, rm: Function) { const el: any = vnode.elm
if (isDef(el._enterCb)) { el._enterCb.cancelled = true el._enterCb() }
const data = resolveTransition(vnode.data.transition) const { css, type, leaveClass, leaveToClass, leaveActiveClass, beforeLeave, leave, afterLeave, leaveCancelled, delayLeave, duration } = data
const cb = el._leaveCb = once(() => { if (expectsCSS) { removeTransitionClass(el, leaveToClass) removeTransitionClass(el, leaveActiveClass) } if (cb.cancelled) { if (expectsCSS) { removeTransitionClass(el, leaveClass) } leaveCancelled && leaveCancelled(el) } else { rm() afterLeave && afterLeave(el) } el._leaveCb = null })
if (delayLeave) { delayLeave(performLeave) } else { performLeave() }
function performLeave () { if (cb.cancelled) { return } beforeLeave && beforeLeave(el) if (expectsCSS) { addTransitionClass(el, leaveClass) addTransitionClass(el, leaveActiveClass) nextFrame(() => { addTransitionClass(el, leaveToClass) removeTransitionClass(el, leaveClass) if (!cb.cancelled && !userWantsControl) { if (isValidDuration(explicitLeaveDuration)) { setTimeout(cb, explicitLeaveDuration) } else { whenTransitionEnds(el, type, cb) } } }) }
leave && leave(el, cb) if (!expectsCSS && !userWantsControl) { cb() } } }
|
嗯,大概是这些的逻辑啦,现在大家明白了leave: function (el, done)
里的 done 是什么了吧~
结束语
本节我们介绍了 Vue 动画中的 Javascript 钩子,以及相关的一些源码分析。很多时候我们看一个框架内容好多好复杂,其实慢慢理解和思考,一点点拆分下来也不是特别难的啦。
查看Github有更多内容噢:https://github.com/godbasin
更欢迎来被删的前端游乐场边撸猫边学前端噢
如果你想要关注日常生活中的我,欢迎关注“牧羊的猪”公众号噢