背景
由于前端在平时的工作中会经常与页面打交道,在工作中往往按照设计师给定的设计图进行开发,而大多数时候,设计图并不会点出具体的实现的动效。这就导致很多时候我们做出来的东西失去活力,比如按钮的hover特效、背景的渐变特效等。而Vue框架本身就提供了一些api去做这样的工作,今天就由我跟大家一起去了解一下,vue列表过渡,会学习到关于Vue列表过渡的使用,以及对于列表过渡的封装实践。最后会给大家看一下我在平时的工作中对于列表过渡以及Vue动画的一些应用,以及我自己封装实现的列表过渡的方法和组件。
单元素和单组件的过渡
触发条件
条件渲染 (使用 v-if)
条件展示 (使用 v-show)
动态组件 component is (指挥系统中任务调度详情有使用到)
组件根节点 进行渲染组件的时候会触发
css类名
一共有6个,分别对应过渡的各个阶段。分别是v-enter、v-enter-active、v-enter-to、v-leave、v-leave-active、v-leave-to。对应的过程分别是过渡进入的开始状态、进入的生效状态、进入的结束状态、离开的开始状态、离开的生效状态、离开的结束状态;
当组件没有name属性的时候类名前缀会默认用v,当有name属性的时候前缀则用name属性的名称代替。
注:可以在写css的时候优先使用动画
钩子函数
<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>
当需要在第一次渲染的时候就使用过渡,可以在组件添加一个appear属性;
标签只能用来包裹单元素, 严格说transition中不一定非得是单元素。也可以有多个元素,但是必须要使用v-if来控制其显隐。确保只能有一个处于显示状态的单元素。
无论是过渡还是动画,原理都是在特定的时间为transtion包裹的最外层元素添加和删除class名
为什么Vue知道动画或者过渡什么时候执行完了? 有什么办法去自己定义什么时候执行过渡?
多元素和多组件的过渡
多元素的过渡
多元素的过渡一般用v-if/v-else去实现,常见的用于判断一个列表里面的项为空的情况;
<transition>
<table v-if="items.length > 0">
<!-- ... -->
</table>
<p v-else>Sorry, no items found.</p>
</transition>
当标签名相同的时候,最好是添加一个key值去区分,由于vue的内部机制,会只替换相同标签里的内容而不是整个标签进行替换
过渡模式
通过在transition添加mode属性.
in-out:新元素先进行过渡,完成之后当前元素过渡离开。
out-in:当前元素先进行过渡,完成之后新元素过渡进入。
<transition name="fade" mode="out-in">
<!-- ... the buttons ... -->
</transition>
多组件的过渡
通过配合动态组件去实现
<transition name="component-fade" mode="out-in">
<component v-bind:is="view"></component>
</transition>
在指挥的3.0任务调度中有使用到
列表过渡
应用
以下引用原文:原文 侵删
过渡的demo
动态跟进、段落列表、翻转列表、交错列表
// 动态跟进
@keyframes one-in {
from {
padding-top: 100px;
height: 0%;
}
to {
padding-top: 0px;
height: 100%;
}
}
//段落列表
@keyframes one-in {
from {
padding-left: 100%;
}
to {
padding-left: 0%;
}
}
//翻转列表
@keyframes one-in {
from {
height: 100%;
transform: rotateX(75deg);
}
to {
height: 100%;
transform: rotateX(0deg);
/* transform-origin: 145%, 0; */
}
}
//交错列表
@keyframes one-in {
from {
padding-left: 100%;
height: 0;
}
to {
padding-left: 0%;
height: 100px;
}
}
@keyframes two-in {
from {
padding-right: 100%;
padding-top: 100px;
height: 0;
}
to {
padding-right: 0%;
padding-top: 0px;
height: 100px;
}
}
动态跟进列表
跟进列表是从下出现,回到初始位置,我在初始阶段采用了padding-top为100%,结束阶段为0%实现这个动画(margin-top也可以实现这个动画)
主要的实现代码:
// 动态跟进
@keyframes one-in {
from {
padding-top: 100px;
height: 0%;
}
to {
padding-top: 0px;
height: 100%;
}
}
段落列表
段落列表是从右出现,回到正常位置,我在初始阶段采用了padding-left为100%,结束阶段为0%实现这个动画(margin-left也可以实现这个动画)
主要的实现代码:
//段落列表
@keyframes one-in {
from {
padding-left: 100%;
}
to {
padding-left: 0%;
}
}
翻转列表
交错列表
交错列表稍微复杂点,不过我们可以分解为两个动画。
@keyframes one-in {
from {
padding-right: 100%;
padding-top: 100px;
height: 0;
}
to {
padding-right: 0%;
padding-top: 0px;
height: 100px;
}
}
@keyframes Two-in {
from {
padding-left: 100%;
height: 0;
}
to {
padding-left: 0%;
height: 100px;
}
}
然后根据列表渲染的index为奇数或偶数选择不同的动画
methods: {
beforeEnter (el) {
el.style.opacity = 0
},
enter (el, done) {
let delay = el.dataset.index * 100
let animation = el.dataset.index % 2 === 0
? 'one-in 0.4s infinite'
: 'two-in 0.4s infinite'
setTimeout(()=>{
el.style.transition = 'opacity 0.4s '
el.style.opacity = 1
el.style.animation = animation
el.style['animation-iteration-count'] = 1
done()
}, delay)
}
}
创建可复用的过渡
过渡在3.0项目中的运用
1、示例 协同标会系统首页地图列表加载、主页地图分享列表
2、关于此封装的优缺点
优点: 可使v-for渲染的列表更具有活力
缺点:没有考虑到滚动条的防抖
疑问?为什么在vue项目中要使用asyn和await去设置每一条列表的动画?
滚动条闪烁的优化应该怎么做?
如果不用setTimeout去设置动画,还有没有更好的实现方式?
使用vue组件跟Vue过渡去重新封装这个组件的话,应该怎么去做?
因为Vue监听了目标元素【也就是transition标签包裹的最外层的这个元素】的transitionend和animationend这两个事件;
duration这个prop会强制的指定动画需要多少时间执行完毕,当指定了这个prop之后。就不再根据transitionend和animationend这两个事件来决定什么时候执行完毕然后删除class名了。时间一到就直接删除class名。如果duration指定的时间大于animation-duration或者tansition-duration,动画或者过渡执行完毕,也不会删除掉class名,而是等duration这个prop指定的时间结束之后再删除
github : github地址