炫意html5
最早CSS3和HTML5移动技术网站之一

进阶教程 – vue.js 2.0 过渡效果

概述

Vue 在插入、更新或者移除 DOM 时,提供多种不同方式的应用过渡效果。
包括以下工具:

  • 在 CSS 过渡和动画中自动应用 class
  • 可以配合使用第三方 CSS 动画库,如 Animate.css
  • 在过渡钩子函数中使用 JavaScript 直接操作 DOM
  • 可以配合使用第三方 JavaScript 动画库,如 Velocity.js

在这里,我们只会讲到进入、离开和列表的过渡, 你也可以看下一节的 管理过渡状态.

单元素/组件的过渡

Vue 提供了 transition 的封装组件,在下列情形中,可以给任何元素和组件添加 entering/leaving 过渡

  • 条件渲染 (使用 v-if
  • 条件展示 (使用 v-show
  • 动态组件
  • 组件根节点

这里是一个典型的例子:

<div id="demo">
<button v-on:click="show = !show">
Toggle
</button>
<transition name="fade">
<p v-if="show">hello</p>
</transition>
</div>
new Vue({
el: '#demo',
data: {
show: true
}
})
.fade-enter-active, .fade-leave-active {
transition: opacity .5s
}
.fade-enter, .fade-leave-active {
opacity: 0
}

hello

元素封装成过渡组件之后,在遇到插入或删除时,Vue 将
1. 自动嗅探目标元素是否有 CSS 过渡或动画,并在合适时添加/删除 CSS 类名。
2. 如果过渡组件设置了过渡的 [JavaScript 钩子函数](#JavaScript-Hooks),会在相应的阶段调用钩子函数。
3. 如果没有找到 JavaScript 钩子并且也没有检测到 CSS 过渡/动画,DOM 操作(插入/删除)在下一帧中立即执行。(注意:此指浏览器逐帧动画机制,与 Vue,和Vue的 `nextTick` 概念不同)
### 过渡的-CSS-类名
会有 4 个(CSS)类名在 enter/leave 的过渡中切换
1. `v-enter`: 定义进入过渡的开始状态。在元素被插入时生效,在下一个帧移除。
2. `v-enter-active`: 定义进入过渡的结束状态。在元素被插入时生效,在 `transition/animation` 完成之后移除。
3. `v-leave`: 定义离开过渡的开始状态。在离开过渡被触发时生效,在下一个帧移除。
4. `v-leave-active`: 定义离开过渡的结束状态。在离开过渡被触发时生效,在 `transition/animation` 完成之后移除。
![Transition Diagram](/images/transition.png)
对于这些在 `enter/leave` 过渡中切换的类名,`v-` 是这些类名的前缀。使用 `` 可以重置前缀,比如 `v-enter` 替换为 `my-transition-enter`。
`v-enter-active` 和 `v-leave-active` 可以控制 进入/离开 过渡的不同阶段,在下面章节会有个示例说明。
### CSS 过渡
常用的过渡都是使用 CSS 过渡。
下面是一个简单例子:
“` html


hello

“`
“` js
new Vue({
el: ‘#example-1’,
data: {
show: true
}
})
“`
“` css
/* 可以设置不同的进入和离开动画 */
/* 设置持续时间和动画函数 */
.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-active {
padding-left: 10px;
opacity: 0;
}
“`


hello

### CSS 动画
CSS 动画用法同 CSS 过渡,区别是在动画中 `v-enter` 类名在节点插入 DOM 后不会立即删除,而是在 `animationend` 事件触发时删除。
示例: (省略了兼容性前缀)
“` html


Look at me!

“`
“` js
new Vue({
el: ‘#example-2’,
data: {
show: true
}
})
“`
“` css
.bounce-enter-active {
animation: bounce-in .5s;
}
.bounce-leave-active {
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);
}
}
“`


Look at me!

### 自定义过渡类名
我们可以通过以下特性来自定义过渡类名:
– `enter-class`
– `enter-active-class`
– `leave-class`
– `leave-active-class`
他们的优先级高于普通的类名,这对于 Vue 的过渡系统和其他第三方 CSS 动画库,如 [Animate.css](https://daneden.github.io/animate.css/) 结合使用十分有用。
示例:
“` html


hello

“`
“` js
new Vue({
el: ‘#example-3’,
data: {
show: true
}
})
“`


hello

### 同时使用 Transitions 和 Animations
Vue 为了知道过渡的完成,必须设置相应的事件监听器。它可以是 `transitionend` 或 `animationend` ,这取决于给元素应用的 CSS 规则。如果你使用其中任何一种,Vue 能自动识别类型并设置监听。
但是,在一些场景中,你需要给同一个元素同时设置两种过渡动效,比如 `animation` 很快的被触发并完成了,而 `transition` 效果还没结束。在这种情况中,你就需要使用 `type` 特性并设置 `animation` 或 `transition` 来明确声明你需要 Vue 监听的类型。
### JavaScript 钩子
可以在属性中声明 JavaScript 钩子
“` html
“`
“` js
// …
methods: {
// ——–
// 进入中
// ——–
beforeEnter: function (el) {
// …
},
// 此回调函数是可选项的设置
// 与 CSS 结合时使用
enter: function (el, done) {
// …
done()
},
afterEnter: function (el) {
// …
},
enterCancelled: function (el) {
// …
},
// ——–
// 离开时
// ——–
beforeLeave: function (el) {
// …
},
// 此回调函数是可选项的设置
// 与 CSS 结合时使用
leave: function (el, done) {
// …
done()
},
afterLeave: function (el) {
// …
},
// leaveCancelled 只用于 v-show 中
leaveCancelled: function (el) {
// …
}
}
“`
这些钩子函数可以结合 CSS `transitions/animations` 使用,也可以单独使用。

当只用 JavaScript 过渡的时候, ** 在 `enter` 和 `leave` 中,回调函数 `done` 是必须的 **。 否则,它们会被同步调用,过渡会立即完成。

推荐对于仅使用 JavaScript 过渡的元素添加 `v-bind:css=”false”`,Vue 会跳过 CSS 的检测。这也可以避免过渡过程中 CSS 的影响。

一个使用 Velocity.js 的简单例子:
“` html


Demo

“`
“` js
new Vue({
el: ‘#example-4’,
data: {
show: false
},
methods: {
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 })
}
}
})
“`


Demo

## 初始渲染的过渡
可以通过 `appear` 特性设置节点的在初始渲染的过渡
“` html
“`
这里默认和进入和离开过渡一样,同样也可以自定义 CSS 类名。
“` html
“`
自定义 JavaScript 钩子:
“` html
“`
## 多个元素的过渡
我们之后讨论 [多个组件的过渡](#多个组件的过渡), 对于原生标签可以使用 `v-if`/`v-else` 。最常见的多标签过渡是一个列表和描述这个列表为空消息的元素:
“` html

Sorry, no items found.

“`
可以这样使用,但是有一点需要注意:

当有**相同标签名**的元素切换时,需要通过 `key` 特性设置唯一的值来标记以让 Vue 区分它们,否则 Vue 为了效率只会替换相同标签内部的内容。即使在技术上没有必要,**给在 `` 组件中的多个元素设置 key 是一个更好的实践。**

示例:
“` html


“`
在一些场景中,也可以给通过给同一个元素的 `key` 特性设置不同的状态来代替 `v-if` 和 `v-else`,上面的例子可以重写为:
“` html

“`
使用多个 `v-if` 的多个元素的过渡可以重写为绑定了动态属性的单个元素过渡。 例如:
“` html



“`
可以重写为:
“` html

“`
“` js
// …
computed: {
buttonMessage: function () {
switch (docState) {
case ‘saved’: return ‘Edit’
case ‘edited’: return ‘Save’
case ‘editing’: return ‘Cancel’
}
}
}
“`
### 过渡模式
这里还有一个问题,试着点击下面的按钮:



在 “on” 按钮和 “off” 按钮的过渡中,两个按钮都被重绘了,一个离开过渡的时候另一个开始进入过渡。这是 <transition> 的默认行为 – 进入和离开同时发生。

在元素绝对定位在彼此之上的时候运行正常:



</div>

然后,我们加上 translate 让它们运动像滑动过渡:



同时生效的进入和离开的过渡不能满足所有要求,所以 Vue 提供了 **过渡模式**
– `in-out`: 新元素先进行过渡,完成之后当前元素过渡离开。
– `out-in`: 当前元素先进行过渡,完成之后新元素过渡进入。
用 `out-in` 重写之前的开关按钮过渡:
“` html
“`



只用添加一个简单的特性,就解决了之前的过渡问题而无需任何额外的代码。
`in-out` 模式不是经常用到,但对于一些稍微不同的过渡效果还是有用的。
将之前滑动淡出的例子结合:



很酷吧?
## 多个组件的过渡
多个组件的过渡很简单很多 – 我们不需要使用 `key` 特性。相反,我们只需要使用[动态组件](components.html#动态组件):
“` html

“`
“` js
new Vue({
el: ‘#transition-components-demo’,
data: {
view: ‘v-a’
},
components: {
‘v-a’: {
template: ‘

Component A


},
‘v-b’: {
template: ‘

Component B


}
}
})
“`
“` css
.component-fade-enter-active, .component-fade-leave-active {
transition: opacity .3s ease;
}
.component-fade-enter, .component-fade-leave-active {
opacity: 0;
}
“`


炫意HTML5 » 进阶教程 – vue.js 2.0 过渡效果

CSS3教程HTML5教程