在冷冰冰的网页上,加上些许过渡或动画,其变化虽小,却能极大的提升页面质感,给人一种顺畅、丝滑的视觉体验。它的实现过程主要是通过css中的transition
和animation
来实现的。
而在vue框架中也对此进行了封装,提供了便捷的过渡用法。
1、transition组件用法
在业务开发过程中,最常用的还是transition组件的用法:
<transition name="slide-fade">
<p v-if="show"> hello world </p>
</transition>
/* 可以设置不同的进入和离开动画 */
/* 设置持续时间和动画函数 */
.slide-fade-enter-active {
transition: all .3s ease;
}
.slide-fade-leave-active {
transition: all .8s cubic-bezier(1.0, 0.5, 0.8, 1.0);
}
.slide-fade-enter, .slide-fade-leave-to
transform: translateX(10px);
opacity: 0;
}
在进入/离开的过渡中,主要有 6 个 钩子被触发,并对应6个class 切换。
如果你的transition
组件没有设置name
属性,则 v-
是这些类名的默认前缀。如果你使用了<transition name="my-transition">
,那么 v-enter
会替换为 my-transition-enter
。
这6种class类名可以自定义,他们的优先级高于普通的类名:
<transition name="slide-fade"
enter-active-class="custom-enter-active-class"
leave-active-class="custom-leave-active-class">
<p v-if="show"> hello world </p>
</transition>
/* css部分 */
.custom-enter-active-class {
animation: bounce-in .5s;
}
.custom-leave-active-class {
animation: bounce-in .5s reverse;
}
@keyframes bounce-in {
0% {
transform: scale(0);
}
50% {
transform: scale(1.5);
}
100% {
transform: scale(1);
}
}
另外在不同组件中切换过渡:
<transition name="component-fade" mode="out-in">
<component :is="view"></component>
</transition>
export default {
data () {
return {
view: 'v-a'
}
},
components: {
'v-a': {
template: '<div>Component A</div>'
},
'v-b': {
template: '<div>Component B</div>'
}
}
}
默认情况下,上述两个组件的进入和离开是同时发生的,一个离开过渡的时候另一个开始进入过渡,只有离开的组件完成动画之后,才会把位置让出来,通常这会造成一种卡顿的效果(如果两个元素都设置了绝对定位,则没有这个问题)。
可以通过添加过渡模式mode来满足我们的需求:
in-out
:新元素先进行过渡,完成之后当前元素过渡离开。out-in
:当前元素先进行过渡,完成之后新元素过渡进入。
通常我们更多的会使用out-in
,让当前元素先离开,然后再进行新元素的进入。
<transition name="fade" mode="out-in">
<!-- 不同元素 -->
</transition>
了解了以上的用法,基本就可以实现大部分业务场景了。
2、使用JavaScript动态过渡
在大部分场景下,我们主要是使用css来进行过渡,css已经前置写好了,但在某些情况下,我们还需要动态过渡。
动态过渡最基本的操作就是绑定动态属性,比如name
,当有不同的情况时切换不同的过渡效果。
<transition :name="transitionName">
<!-- ... -->
</transition>
不过这同样需要我们提前写好对应的过渡效果,除此之外,最直接的实现动态过渡的方式是使用JavaScript过渡:
<transition
@before-enter="beforeEnter"
@enter="enter"
@after-enter="afterEnter"
@enter-cancelled="enterCancelled"
@before-leave="beforeLeave"
@leave="leave"
@after-leave="afterLeave"
@leave-cancelled="leaveCancelled"
>
<!-- ... -->
</transition>
methods: {
// 过渡进入之前触发
beforeEnter: function (el) { },
// 过渡进入时触发
enter: function (el, done) {
// ...
// 当与 CSS 结合使用时,回调函数 done 是可选的
// 不用CSS过渡,设置了:css="false",则必须使用回调done
done()
},
// 过渡进入结束时触发
afterEnter: function (el) { },
// 过渡进入被取消时触发
enterCancelled: function (el) { },
// 在离开之前触发
beforeLeave: function (el) { },
// 离开时触发
leave: function (el, done) {
// ...
// 当与 CSS 结合使用,回调函数 done 是可选的
// 不用CSS过渡,设置了:css="false",则必须使用回调done
done()
},
// 离开后触发
afterLeave: function (el) { },
// 离开过程被取消时触发(只用于 v-show 中)
leaveCancelled: function (el) { }
}
上面这些JavaScript过渡钩子可以和 CSS transitions/animations
同时使用,也可以单独使用。
不过既然你都使用了 JavaScript 过渡,那么推荐就不用CSS过渡,元素添加 v-bind:css="false"
,Vue 会跳过 CSS 的检测。这也可以避免过渡过程中 CSS 的影响。
如这个例子:
<!-- Velocity 和 jQuery.animate 的工作方式类似,也是用来实现 JavaScript 动画的一个很棒的选择 -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/velocity/1.2.3/velocity.min.js"></script>
<div id="example-4">
<button @click="show = !show">
Toggle
</button>
<transition
@before-enter="beforeEnter"
@enter="enter"
@leave="leave"
:css="false"
>
<p v-if="show">
Demo
</p>
</transition>
</div>
new Vue({
el: '#example-4',
data: {
show: false
},
methods: {
// 钩子函数里写具体的过渡数据,可以实现js动态控制
beforeEnter: function (el) {
el.style.opacity = 0
el.style.transformOrigin = 'left'
},
enter: function (el, done) {
Velocity(el, { opacity: 1, fontSize: '1.4em' }, { duration: 300 })
Velocity(el, { fontSize: '1em' }, { complete: done })
},
leave: function (el, done) {
Velocity(el, { translateX: '15px', rotateZ: '50deg' }, { duration: 600 })
Velocity(el, { rotateZ: '100deg' }, { loop: 2 })
Velocity(el, {
rotateZ: '45deg',
translateY: '30px',
translateX: '30px',
opacity: 0
}, { complete: done })
}
}
})
3、初始渲染appear
上述过渡的用法通常需要元素或者组件有变化才会触发,如需要v-if
、v-show
、动态组件
等。
如果你的需求是第一次进页面的时候,它就过渡渲染出来,之后是不需要再过渡的,那可以使用appear
这个属性。如下面这个示例:
<!-- appear 也可以自定义 CSS 类名 -->
<transition appear
appear-class="custom-appear-class"
appear-active-class="custom-appear-active-class"
appear-to-class="custom-appear-to-class">
<p>我是一段测试appear初始渲染文字</p>
</transition>
.custom-appear-class{
opacity: 0;
}
.custom-appear-active-class{
transition: all 3s;
}
.custom-appear-to-class{
opacity: 1;
}
appear
和enter
有点像,但它只在初始渲染的时候触发,并且只要把触发之前和触发之后的状态设置不同,便可以实现中间的自然过渡。
同时,它也可以用JavaScript钩子函数实现:
<transition appear
@before-appear="customBeforeAppearHook"
@appear="customAppearHook"
@after-appear="customAfterAppearHook"
@appear-cancelled="customAppearCancelledHook">
<!-- ... -->
</transition>
4、列表过渡和v-move
同一时间内渲染单个节点,或者多个节点中的一个,使用<transition>
组件,如果同时渲染多个节点,比如整个列表,则需要用<transition-group>
组件,该组件有几个特点:
- 不同于
<transition>
,它会以一个真实元素呈现:默认为一个<span>
。可以通过tag
属性更换为其他元素。 - 列表渲染中没有过渡模式。
- 内部元素必须要提供
key
值。
<!-- 设置tag属性为p元素,v-for中的每一项设置key值 -->
<!-- items为一个连续数字组成的数组 [0, 1, 2, ...] -->
<transition-group name="list" tag="p" class="list-item">
<span v-for="item in items" :key="item">
{{ item }}
</span>
</transition-group>
.list-item {
display: inline-block;
margin-right: 10px;
}
.list-enter-active, .list-leave-active {
transition: all 1s;
}
.list-enter, .list-leave-to {
opacity: 0;
transform: translateY(30px);
}
效果如上,但是这有一个问题:当添加和移除元素的时候,周围的元素会瞬间移动到他们的新布局的位置,有一种卡顿的感觉。
要解决这个问题可以通过<transition-group>
组件中的 v-move
class,它会在元素的改变定位的过程中应用。像之前的类名一样,可以通过 name
attribute 来自定义前缀,也可以通过 move-class
attribute 手动设置。
于是只要在上面的例子中修改一下css:
.list-item {
display: inline-block;
margin-right: 10px;
}
/* 这里增加和一个.list-move类样式,它会在元素改变的过程中生效 */
.list-move{
transition: all 1s;
}
.list-enter-active, .list-leave-active {
transition: all 1s;
}
/* 这里在元素离开时增加一个绝对定位属性 */
/* 这样元素离开的瞬间就会触发改变位置,使上面的.list-move生效 */
/* 如果不加绝对定位,则元素离开动作完成后周围的元素才会移动到它的位置 */
/* 而那个时候所有过渡已结束 .list-move已经被移除,会造成卡顿感觉 */
.list-leave-active {
position: absolute;
}
.list-enter, .list-leave-to {
opacity: 0;
transform: translateY(30px);
}
如此就有了一种丝滑的感觉,另外上述css可进一步修改简化:
/* 直接在元素上增加transition属性 */
/* 它会在元素改变的所有过程中生效,包括v-move的时候 */
.list-item {
display: inline-block;
margin-right: 10px;
transition: all 1s;
}
/* 因此v-move和v-active相关的均可不需要了 */
/* 只要在元素离开时增加一个绝对定位属性即可 */
.list-leave-active {
position: absolute;
}
.list-enter, .list-leave-to {
opacity: 0;
transform: translateY(30px);
}
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!