过渡

使用 Vue.js 的过渡系统,您可以在元素插入或从 DOM 中移除时应用自动过渡效果。Vue.js 会在适当的时间自动添加/移除 CSS 类,以触发 CSS 过渡或动画,您还可以提供 JavaScript 钩子函数,以便在过渡期间执行自定义 DOM 操作。

要应用过渡效果,您需要在目标元素上使用特殊的 transition 属性

<div v-if="show" transition="my-transition"></div>

transition 属性可以与以下内容一起使用

当具有过渡的元素被插入或移除时,Vue 会

  1. 尝试查找通过 Vue.transition(id, hooks) 注册或通过 transitions 选项传递的 JavaScript 过渡钩子对象,使用 id "my-transition"。如果找到,它将在过渡的不同阶段调用相应的钩子。

  2. 自动嗅探目标元素是否应用了 CSS 过渡或 CSS 动画,并在适当的时间添加/移除 CSS 类。

  3. 如果没有提供 JavaScript 钩子,并且没有检测到 CSS 过渡/动画,则 DOM 操作(插入/移除)将在下一帧立即执行。

CSS 过渡

示例

典型的 CSS 过渡如下所示

<div v-if="show" transition="expand">hello</div>

您还需要为 .expand-transition.expand-enter.expand-leave 类定义 CSS 规则

/* always present */
.expand-transition {
transition: all .3s ease;
height: 30px;
padding: 10px;
background-color: #eee;
overflow: hidden;
}
/* .expand-enter defines the starting state for entering */
/* .expand-leave defines the ending state for leaving */
.expand-enter, .expand-leave {
height: 0;
padding: 0 10px;
opacity: 0;
}

您可以通过使用动态绑定在同一个元素上实现不同的过渡

<div v-if="show" :transition="transitionName">hello</div>
new Vue({
el: '...',
data: {
show: false,
transitionName: 'fade'
}
})

此外,您可以提供 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
}
})
你好

过渡 CSS 类

添加和切换的类基于 transition 属性的值。在 transition="fade" 的情况下,涉及三个 CSS 类

  1. .fade-transition 将始终存在于元素上。

  2. .fade-enter 定义进入过渡的起始状态。它应用于单帧,然后立即移除。

  3. .fade-leave 定义离开过渡的结束状态。它在离开过渡开始时应用,并在过渡结束时移除。

如果 transition 属性没有值,则类将默认为 .v-transition.v-enter.v-leave

自定义过渡类

1.0.14 中的新功能

您可以在过渡定义中指定自定义 enterClassleaveClass。这些将覆盖传统的类名。当您想将 Vue 的过渡系统与现有的 CSS 动画库(例如 Animate.css)结合使用时,这很有用。

<div v-show="ok" class="animated" transition="bounce">Watch me bounce</div>
Vue.transition('bounce', {
enterClass: 'bounceInLeft',
leaveClass: 'bounceOutRight'
})

声明过渡类型

1.0.14 中的新功能

Vue.js 需要附加事件监听器,以便知道过渡何时结束。它可以是 transitionendanimationend,具体取决于应用的 CSS 规则类型。如果您只使用其中一种,Vue.js 可以自动检测正确的类型。但是,在某些情况下,您可能希望在同一个元素上同时使用两者,例如,让 Vue 触发 CSS 动画,并且在悬停时也具有 CSS 过渡效果,您将必须明确声明您希望 Vue 关注的类型。

Vue.transition('bounce', {
// Vue will now only care about `animationend` events
// for this transition
type: 'animation'
})

过渡流程详细信息

show 属性更改时,Vue.js 将相应地插入或移除 <div> 元素,并应用如下所示的过渡类

此外,如果您在进入过渡正在进行时移除元素,则会调用 enterCancelled 钩子,让您有机会清理在 enter 中创建的更改或计时器。离开过渡也是如此。

所有上述钩子函数都以其 this 上下文设置为关联的 Vue 实例调用。它遵循相同的编译范围规则:过渡的 this 上下文将指向它编译所在的范围。

最后,enterleave 可以选择性地接受第二个回调参数。当您这样做时,您表示您希望明确控制过渡何时结束,因此,Vue.js 不会等待 CSS transitionend 事件,而是期望您最终调用回调以完成过渡。例如

enter: function (el) {
// no second argument, transition end
// determined by CSS transitionend event
}

vs.

enter: function (el, done) {
// with the second argument, the transition
// will only end when `done` is called.
}

当多个元素一起过渡时,Vue.js 会将它们批处理,并且只应用一次强制布局。

CSS 动画

CSS 动画与 CSS 过渡的应用方式相同,区别在于 v-enter 不会在元素插入后立即移除,而是在 animationend 事件上移除。

示例:(此处省略带前缀的 CSS 规则)

<span v-show="show" transition="bounce">Look at me!</span>
.bounce-transition {
display: inline-block; /* otherwise scale animation won't work */
}
.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);
}
}
看我!

JavaScript 过渡

您也可以只使用 JavaScript 钩子,而不定义任何 CSS 规则。当只使用 JavaScript 过渡时,enterleave 钩子需要 done 回调,否则它们将同步调用,过渡将立即完成。

为您的 JavaScript 过渡明确声明 css: false 也是一个好主意,这样 Vue.js 就可以跳过 CSS 检测。这也防止了级联 CSS 规则意外干扰过渡。

以下示例使用 jQuery 注册自定义 JavaScript 过渡

Vue.transition('fade', {
css: false,
enter: function (el, done) {
// element is already inserted into the DOM
// call done when animation finishes.
$(el)
.css('opacity', 0)
.animate({ opacity: 1 }, 1000, done)
},
enterCancelled: function (el) {
$(el).stop()
},
leave: function (el, done) {
// same as enter
$(el).animate({ opacity: 0 }, 1000, done)
},
leaveCancelled: function (el) {
$(el).stop()
}
})

然后,您可以使用 transition 属性,操作相同

<p transition="fade"></p>

交错过渡

在使用 transitionv-for 时,可以创建交错过渡。您可以通过将 staggerenter-staggerleave-stagger 属性添加到过渡元素来实现

<div v-for="item in list" transition="stagger" stagger="100"></div>

或者,您可以提供 staggerenterStaggerleaveStagger 钩子,以获得更细粒度的控制

Vue.transition('stagger', {
stagger: function (index) {
// increase delay by 50ms for each transitioned item,
// but limit max delay to 300ms
return Math.min(300, index * 50)
}
})

示例

stagger 属性不会影响由 v-ifv-show 添加或移除的项目的过渡。只有对提供给 v-for 的数组或对象的更改会导致过渡交错。