前言
《vue 基础》系列是再次回炉 vue 记的笔记,除了官网那部分知识点外,还会加入自己的一些理解。(里面会有部分和官网相同的文案,有经验的同学择感兴趣的阅读)
单元素/组件的过渡
示例
vue 提供了 transition 组件标签,来对如下特殊的指令或者标签做 “进入/离开”过渡 效果:
- v-if
- v-show
- 动态组件
- 组件 root 节点
先来看段代码,当点击 button 后,会控制 show 的值来切换 v-if 所要渲染的模板:
1 | <div id="demo"> |
1 | .fade-enter-active, |
实际效果:
那动效怎么产生的呢?
自动嗅探目标元素是否应用了 CSS 过渡或动画,如果是,在恰当的时机添加/删除 CSS 类名。
- 当显示时:添加样式 xx-enter-active xx-enter-to
- 当离开时:添加样式 xx-leave-active xx-leave-to
如果过渡组件提供了 JavaScript 钩子函数,这些钩子函数将在恰当的时机被调用。
- 如果没有找到 JavaScript 钩子并且也没有检测到 CSS 过渡/动画,DOM 操作 (插入/删除) 在下一帧中立即执行。(注意:此指浏览器逐帧动画机制,和 Vue 的 nextTick 概念不同)
过渡的类名
在进入/离开的过渡中,会有 6 个 class 切换:
v-enter –> v-enter-active –> v-enter-to –> v-leave –> v-leave-active –> v-leave-to
css 过渡 & css 动画
过渡
我们可以根据出入场过渡效果,在 css 这样定义:
1 | /* 元素 enter 过渡整个过程 */ |
以上这些都属于 css 过渡的效果。
动画
除了过渡效果,我们还能设置 animation 标签指定 css 动画效果。
1 | .bounce-enter-active { |
同时使用过渡和动画
当然这两者都是 css 范畴的特效知识,根据实际需要使用。
不过可能出现 animation 完成,但 transition 还在继续的情况,对于这种情况需要设置 type=animation|transition 来区分 vue 所要监听的类型。
我们先来看下两种动效单独的使用情况(动画稍显夸张,只为说明现象):
animation
1 | .bounce-enter-active { |
粉色方框按照 animation 设置的进度,逐步放大,直至结束,用时 1s。
transition
1 | .bounce-enter { |
红框从 300px 缩小至 100px,用时 3s。
一起使用
因为动效在时间 duration 中存在重叠交叉,所以会出现上面这样变扭的效果,可以动过 type animation|transition 来指定 vue 监听动效的类型加以控制。
比如,我们设置了 animation 就 屏蔽了 transition 的效果,就会和单使用 animation 一样了。
1 | <transition name="bounce" type="animation"> |
自定义过渡的类名
用于配合第三方 animate 类库时使用。可以根据我们的需要细化效果的展示。
1 | <link href="https://cdn.jsdelivr.net/npm/animate.css@3.5.1" rel="stylesheet" type="text/css" /> |
JavaScript 钩子
可以在标签上绑定过渡各个时期的钩子,通过 js 来调用触发相关事件的事件。
1 | <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"> |
1 | methods: { |
注意:当只用 JavaScript 过渡的时候,在 enter 和 leave 中必须使用 done 进行回调。否则,它们将被同步调用,过渡会立即完成。
多个元素的过渡
举个多元素过渡的例子:
1 | <transition> |
key
如果存在数据就显示 table 内容,不存在就显示一个无数据的文案,然后通过 transition 动效切换不同效果。
但是如果当相同标签元素切换时,就需要通过 key 来区分他们的不同。
1 | <transition> |
如果相同元素模板的 key 一致,效果如下:
注意,这不是期望的效果。可能你会感觉到生硬,因为相同 key 的元素切换时没有过渡效果。
设置不同 key 后,动效得以生效:
过渡模式
在两个元素切换的时候,可能我们需要更细致的过渡模式,比如上例中:第一个 button 离开,第二个 button 进来之间的过程中,都被重新绘制了,间隙虽然很短,但能明显看到产生了类似滑动的效果(不符合原始意图)。
vue 提供了 mode 过渡模式:
- in-out:新元素先进行过渡,完成之后当前元素过渡离开。
- out-in:当前元素先进行过渡,完成之后新元素过渡进入。
当使用 out-in mode 时,第二个元素等待第一个元素消失后才入场,使得原始意图符合预期。
多个组件的过渡
同时 transition 也可以作用于“动态组件”的过渡效果。
1 | <transition name="component-fade" mode="out-in"> |
列表过渡
与 transition 不同的是,列表过渡需要使用 <transition-group> 标签。
1 | <button @click="check">add</button> |
能注意到这里设置了 tag=’div’ ,可以让最后的列表内容包裹在一个 div 标签内。
列表排序过渡
<transition-group> 另一个不同是,可以设置 v-move 属性,类似 v-enter、v-leave。
1 | .fade-move { transition: transform 1s; } |
其他
vue 内置还使用了 FLIP 动画队列,基于数据驱动的方式,能做更多的动画效果展示。这里不再做展开。有兴趣请查看官网示例
总结
简单说了 transation 和 transation-group 单元素和多元素的过渡用法,初步对 vue 在动效上的实现有了一点了解。