使用内置的<Transition>
动画组件<p>
元素被删除时v-if
:
<Transition>
<p v-if="exists">Hello World!</p>
</Transition>
运行示例 »
请参阅下面的更多示例。
内置的<Transition>
组件用于在添加或删除元素时对元素进行动画处理v-if
,v-show
,或带有动态组件。
元素动画的规则是在自动生成的类或 JavaScript 转换挂钩中编写的。请参阅下表。
根级别只能有一个元素<Transition>
成分。
Prop | Description | |
---|---|---|
none | Default. | Run Example » |
appear | If set to true , the element is also animated as it is mounted for the first time. Default value is false . |
Run Example » |
mode | mode="out-in" makes sure that the initial element leaves before the next element enters. mode="in-out" makes sure that the new element enters before the old element leaves. Default is that the old element leaves at the same time as the new element enters. |
Run Example » |
name | Specify the name of a transition. If we have more than one transition we need to give them unique names to tell them apart. name="swirl" makes sure the CSS transition classes start with swirl- instead of the default prefix v- . |
Run Example » |
css | Boolean. :css="false" tells the Vue compiler that no transition classes are used for this transition, only JavaScript hooks. With this prop set, the done() callback must be used inside the enter and leave hooks. |
Run Example » |
type | Specify whether to wait for 'animation' or 'transition' to finish a transition. If both a CSS animation and a CSS transition is set, and this type prop is not set, Vue will detect the longest duration of these two and use that as the transition time. | |
duration | Specify the length of the transition time for 'enter' and 'leave'. Default is to end when the CSS animation or CSS transition ends. Specific times can be defined like this :duration="{enter:2000, leave:1000 }" , or like this duration="1000" . |
|
enterFromClass enterActiveClass enterToClass appearFromClass appearActiveClass appearToClass leaveFromClass leaveActiveClass leaveToClass |
Use these props to rename transition classes. Using one of these props like this |
Run Example » |
当我们使用<Transition>
组件中,我们会自动获取六个不同的 CSS 类,我们可以使用它们在添加或删除元素时对元素进行动画处理。
当添加(进入)或删除(离开)元素时,这些类在不同阶段处于活动状态:
Transition Class | Description | |
---|---|---|
v-enter-from | Initial style of the element when the entering phase starts | Run Example » |
v-enter-active | The element's style during the entering phase | Run Example » |
v-enter-to | The element's style right at the end of the entering phase | Run Example » |
v-leave-from | Initial style of the element when the leaving phase starts | Run Example » |
v-leave-active | The element's style during the leaving phase | Run Example » |
v-leave-to | The element's style right at the end of the leaving phase | Run Example » |
上面的转换类对应于我们可以挂钩以运行 JavaScript 代码的事件。
JavaScript Event | Description | |
---|---|---|
before-enter | Called right at the start of the enter phase | |
enter | Called after the 'before-enter' hook, during the enter phase | Run Example » |
after-enter | Called right at the end of the enter transition | Run Example » |
enter-cancelled | Called if the enter transition is cancelled | Run Example » |
before-leave | Called right at the start of the leave phase | Run Example » |
leave | Called after the 'before-leave' hook, during the leave phase | Run Example » |
after-leave | Called right at the end of the leave transition | |
leave-cancelled | This is only called if v-show is used and the leave phase is cancelled |
<p>
元素在切换时滑入和滑出。
<template>
<h1>Add/Remove <p> Tag</h1>
<button @click="this.exists = !this.exists">{{btnText}}</button><br>
<Transition>
<p v-if="exists">Hello World!</p>
</Transition>
</template>
<script>
export default {
data() {
return {
exists: false
}
},
computed: {
btnText() {
if(this.exists) {
return 'Remove';
}
else {
return 'Add';
}
}
}
}
</script>
<style>
.v-enter-from {
opacity: 0;
translate: -100px 0;
}
.v-enter-to {
opacity: 1;
translate: 0 0;
}
.v-leave-from {
opacity: 1;
translate: 0 0;
}
.v-leave-to {
opacity: 0;
translate: 100px 0;
}
p {
background-color: lightgreen;
display: inline-block;
padding: 10px;
transition: all 0.5s;
}
</style>
运行示例 »
<p>
元素在“进入”和“离开”期间具有单独的背景颜色
<template>
<h1>Add/Remove <p> Tag</h1>
<button @click="this.exists = !this.exists">{{btnText}}</button><br>
<Transition>
<p v-if="exists">Hello World!</p>
</Transition>
</template>
<script>
export default {
data() {
return {
exists: false
}
},
computed: {
btnText() {
if(this.exists) {
return 'Remove';
}
else {
return 'Add';
}
}
}
}
</script>
<style>
.v-enter-active {
background-color: lightgreen;
animation: added 1s;
}
.v-leave-active {
background-color: lightcoral;
animation: added 1s reverse;
}
@keyframes added {
from {
opacity: 0;
translate: -100px 0;
}
to {
opacity: 1;
translate: 0 0;
}
}
p {
display: inline-block;
padding: 10px;
border: dashed black 1px;
}
</style>
运行示例 »
<p>
元素的动画效果不同,使用name
道具来区分<Transition>
成分。
<template>
<h1>Add/Remove <p> Tag</h1>
<p>The second transition in this example has the name prop "swirl", so that we can keep the transitions apart with different class names.</p>
<hr>
<button @click="this.p1Exists = !this.p1Exists">{{btn1Text}}</button><br>
<Transition>
<p v-if="p1Exists" id="p1">Hello World!</p>
</Transition>
<hr>
<button @click="this.p2Exists = !this.p2Exists">{{btn2Text}}</button><br>
<Transition name="swirl">
<p v-if="p2Exists" id="p2">Hello World!</p>
</Transition>
</template>
<script>
export default {
data() {
return {
p1Exists: false,
p2Exists: false
}
},
computed: {
btn1Text() {
if(this.p1Exists) {
return 'Remove';
}
else {
return 'Add';
}
},
btn2Text() {
if(this.p2Exists) {
return 'Remove';
}
else {
return 'Add';
}
}
}
}
</script>
<style>
.v-enter-active {
background-color: lightgreen;
animation: added 1s;
}
.v-leave-active {
background-color: lightcoral;
animation: added 1s reverse;
}
@keyframes added {
from {
opacity: 0;
translate: -100px 0;
}
to {
opacity: 1;
translate: 0 0;
}
}
.swirl-enter-active {
animation: swirlAdded 1s;
}
.swirl-leave-active {
animation: swirlAdded 1s reverse;
}
@keyframes swirlAdded {
from {
opacity: 0;
rotate: 0;
scale: 0.1;
}
to {
opacity: 1;
rotate: 360deg;
scale: 1;
}
}
#p1, #p2 {
display: inline-block;
padding: 10px;
border: dashed black 1px;
}
#p2 {
background-color: lightcoral;
}
</style>
运行示例 »
这个after-enter
事件触发一个<div>
要显示的元素。
<template>
<h1>JavaScript Transition Hooks</h1>
<p>This code hooks into "after-enter" so that after the initial animation is done, a method runs that displays a red div.</p>
<button @click="pVisible=true">Create p-tag!</button><br>
<Transition @after-enter="onAfterEnter">
<p v-show="pVisible" id="p1">Hello World!</p>
</Transition>
<br>
<div v-show="divVisible">This appears after the "enter-active" phase of the transition.</div>
</template>
<script>
export default {
data() {
return {
pVisible: false,
divVisible: false
}
},
methods: {
onAfterEnter() {
this.divVisible = true;
}
}
}
</script>
<style>
.v-enter-active {
animation: swirlAdded 1s;
}
@keyframes swirlAdded {
from {
opacity: 0;
rotate: 0;
scale: 0.1;
}
to {
opacity: 1;
rotate: 360deg;
scale: 1;
}
}
#p1, div {
display: inline-block;
padding: 10px;
border: dashed black 1px;
}
#p1 {
background-color: lightgreen;
}
div {
background-color: lightcoral;
}
</style>
运行示例 »
切换按钮会触发enter-cancelled
事件。
<template>
<h1>The 'enter-cancelled' Event</h1>
<p>Click the toggle button again before the enter animation is finished to trigger the 'enter-cancelled' event.</p>
<button @click="pVisible=!pVisible">Toggle</button><br>
<Transition @enter-cancelled="onEnterCancelled">
<p v-if="pVisible" id="p1">Hello World!</p>
</Transition>
<br>
<div v-if="divVisible">You interrupted the "enter-active" transition.</div>
</template>
<script>
export default {
data() {
return {
pVisible: false,
divVisible: false
}
},
methods: {
onEnterCancelled() {
this.divVisible = true;
}
}
}
</script>
<style>
.v-enter-active {
animation: swirlAdded 2s;
}
@keyframes swirlAdded {
from {
opacity: 0;
rotate: 0;
scale: 0.1;
}
to {
opacity: 1;
rotate: 720deg;
scale: 1;
}
}
#p1, div {
display: inline-block;
padding: 10px;
border: dashed black 1px;
}
#p1 {
background-color: lightgreen;
}
div {
background-color: lightcoral;
}
</style>
运行示例 »
这个appear
道具开始<p>
页面加载后立即进行元素动画。
<template>
<h1>The 'appear' Prop</h1>
<p>The 'appear' prop starts the animation when the p tag below is rendered for the first time as the page opens. Without the 'appear' prop, this example would have had no animation.</p>
<Transition appear>
<p id="p1">Hello World!</p>
</Transition>
</template>
<style>
.v-enter-active {
animation: swirlAdded 1s;
}
@keyframes swirlAdded {
from {
opacity: 0;
rotate: 0;
scale: 0.1;
}
to {
opacity: 1;
rotate: 360deg;
scale: 1;
}
}
#p1 {
display: inline-block;
padding: 10px;
border: dashed black 1px;
background-color: lightgreen;
}
</style>
运行示例 »
通过“进入”和“离开”动画翻阅图片。在删除旧图片之前会添加新图片。
<template>
<h1>Transition Between Elements</h1>
<p>Click the button to get a new image.</p>
<p>The new image is added before the previous is removed. We will fix this in the next example with mode="out-in".</p>
<button @click="newImg">Next image</button><br>
<Transition>
<img src="/img_pizza.svg" v-if="imgActive === 'pizza'">
<img src="/img_apple.svg" v-else-if="imgActive === 'apple'">
<img src="/img_cake.svg" v-else-if="imgActive === 'cake'">
<img src="/img_fish.svg" v-else-if="imgActive === 'fish'">
<img src="/img_rice.svg" v-else-if="imgActive === 'rice'">
</Transition>
</template>
<script>
export default {
data() {
return {
imgActive: 'pizza',
imgs: ['pizza', 'apple', 'cake', 'fish', 'rice'],
indexNbr: 0
}
},
methods: {
newImg() {
this.indexNbr++;
if(this.indexNbr >= this.imgs.length) {
this.indexNbr = 0;
}
this.imgActive = this.imgs[this.indexNbr];
}
}
}
</script>
<style>
.v-enter-active {
animation: swirlAdded 1s;
}
.v-leave-active {
animation: swirlAdded 1s reverse;
}
@keyframes swirlAdded {
from {
opacity: 0;
rotate: 0;
scale: 0.1;
}
to {
opacity: 1;
rotate: 360deg;
scale: 1;
}
}
img {
width: 100px;
margin: 20px;
}
img:hover {
cursor: pointer;
}
</style>
运行示例 »
通过“进入”和“离开”动画翻阅图片。这mode="out-in"
阻止添加新图片,直到删除旧图片。
<template>
<h1>mode="out-in"</h1>
<p>Click the button to get a new image.</p>
<p>With mode="out-in", the next image is not added until the current image is removed. Another difference from the previous example, is that here we use computed prop instead of a method.</p>
<button @click="indexNbr++">Next image</button><br>
<Transition mode="out-in">
<img src="/img_pizza.svg" v-if="imgActive === 'pizza'">
<img src="/img_apple.svg" v-else-if="imgActive === 'apple'">
<img src="/img_cake.svg" v-else-if="imgActive === 'cake'">
<img src="/img_fish.svg" v-else-if="imgActive === 'fish'">
<img src="/img_rice.svg" v-else-if="imgActive === 'rice'">
</Transition>
</template>
<script>
export default {
data() {
return {
imgs: ['pizza', 'apple', 'cake', 'fish', 'rice'],
indexNbr: 0
}
},
computed: {
imgActive() {
if(this.indexNbr >= this.imgs.length) {
this.indexNbr = 0;
}
return this.imgs[this.indexNbr];
}
}
}
</script>
<style>
.v-enter-active {
animation: swirlAdded 0.7s;
}
.v-leave-active {
animation: swirlAdded 0.7s reverse;
}
@keyframes swirlAdded {
from {
opacity: 0;
rotate: 0;
scale: 0.1;
}
to {
opacity: 1;
rotate: 360deg;
scale: 1;
}
}
img {
width: 100px;
margin: 20px;
}
img:hover {
cursor: pointer;
}
</style>
运行示例 »
组件之间的切换是动画的。
<template>
<h1>Transition with Dynamic Components</h1>
<p>The Transition component wraps around the dynamic component so that the switching can be animated.</p>
<button @click="toggleValue = !toggleValue">Switch component</button>
<Transition mode="out-in">
<component :is="activeComp"></component>
</Transition>
</template>
<script>
export default {
data () {
return {
toggleValue: true
}
},
computed: {
activeComp() {
if(this.toggleValue) {
return 'comp-one'
}
else {
return 'comp-two'
}
}
}
}
</script>
<style>
.v-enter-active {
animation: slideIn 0.5s;
}
@keyframes slideIn {
from {
translate: -200px 0;
opacity: 0;
}
to {
translate: 0 0;
opacity: 1;
}
}
.v-leave-active {
animation: slideOut 0.5s;
}
@keyframes slideOut {
from {
translate: 0 0;
opacity: 1;
}
to {
translate: 200px 0;
opacity: 0;
}
}
#app {
width: 350px;
margin: 10px;
}
#app > div {
border: solid black 2px;
padding: 10px;
margin-top: 10px;
}
</style>
运行示例 »
组件之间的切换是动画的。
<template>
<h1>The :css="false" Prop</h1>
<p>With the 'css' prop set to 'false', we tell the compiler that JavaScript hooks are used instead of CSS transition classes.</p>
<p>When we use :css="false", we must call done() inside the 'enter' and the 'leave' hooks, to tell the browser when those transitions are finished.</p>
<button @click="pVisible=!pVisible">Toggle</button>
<div>
<Transition
:css="false"
@enter="onEnter"
@after-enter="onAfterEnter"
@before-leave="onBeforeLeave"
@leave="onLeave"
>
<p
v-if="pVisible"
id="p1">
Hello World!
</p>
</Transition>
</div>
</template>
<script>
export default {
data() {
return {
pVisible: false
}
},
methods: {
onEnter(el,done) {
let pos = 0;
window.requestAnimationFrame(frame);
function frame() {
if (pos > 150) {
done();
} else {
pos++;
el.style.left = pos + "px";
window.requestAnimationFrame(frame);
}
}
},
onAfterEnter(el) {
el.style.backgroundColor = "yellow";
},
onBeforeLeave(el) {
el.style.backgroundColor = "lightgreen";
},
onLeave(el,done) {
let pos = 150;
window.requestAnimationFrame(frame);
function frame() {
if (pos < 0) {
done();
}
else {
pos--;
el.style.left = pos + "px";
window.requestAnimationFrame(frame);
}
}
}
}
}
</script>
<style>
#p1 {
position: absolute;
padding: 10px;
border: dashed black 1px;
background-color: lightgreen;
}
#app > div {
position: relative;
background-color: coral;
width: 300px;
height: 300px;
border: dashed black 1px;
margin-top: 20px;
}
</style>
运行示例 »
使用enterActiveClass
prop 将“v-enter-active”CSS 类重命名为“entering”。
<template>
<h1>The 'enterActiveClass' Prop</h1>
<button @click="this.exists = !this.exists">{{btnText}}</button><br>
<Transition enter-active-class="entering">
<p v-if="exists">Hello World!</p>
</Transition>
</template>
<script>
export default {
data() {
return {
exists: false
}
},
computed: {
btnText() {
if(this.exists) {
return 'Remove';
}
else {
return 'Add';
}
}
}
}
</script>
<style>
.entering {
background-color: lightgreen;
animation: added 1s;
}
.v-leave-active {
background-color: lightcoral;
animation: added 1s reverse;
}
@keyframes added {
from {
opacity: 0;
translate: -100px 0;
}
to {
opacity: 1;
translate: 0 0;
}
}
p {
display: inline-block;
padding: 10px;
border: dashed black 1px;
}
</style>
运行示例 »
Vue教程:Vue 动画
Vue教程:使用 v-for 的 Vue 动画
Vue参考:Vue <TransitionGroup> 组件