Thành phần Vue <Transition>
Ví dụ
Sử dụng thành phần <Transition>
tích hợp sẵn để tạo hiệu ứng cho phần tử <p>
khi nó bị xóa bằng v-if
:
<Transition>
<p v-if="exists">Hello World!</p>
</Transition>
Chạy ví dụ »Xem thêm ví dụ dưới đây.
Định nghĩa và cách sử dụng
Thành phần <Transition>
tích hợp được sử dụng để tạo hiệu ứng cho các phần tử khi chúng được thêm hoặc xóa bằng v-if
, v-show
hoặc với các thành phần động.
Các quy tắc về cách tạo hoạt ảnh cho các phần tử được viết bên trong các lớp được tạo tự động hoặc các móc chuyển tiếp JavaScript. Xem bảng dưới đây.
Chỉ có thể có một phần tử ở cấp độ gốc của thành phần <Transition>
.
đạo cụ
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 » |
Các lớp chuyển tiếp CSS
Khi sử dụng thành phần <Transition>
, chúng tôi tự động nhận được sáu lớp CSS khác nhau mà chúng tôi có thể sử dụng để tạo hiệu ứng cho các phần tử khi chúng được thêm hoặc xóa.
Các lớp này hoạt động ở các giai đoạn khác nhau khi các phần tử được thêm vào (nhập) hoặc xóa (rời):
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 » |
Móc chuyển tiếp JavaScript
Các lớp chuyển tiếp ở trên tương ứng với các sự kiện mà chúng ta có thể nối vào để chạy mã 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 |
Thêm ví dụ
ví dụ 1
Phần tử <p>
trượt vào và trượt ra khi nó được bật/tắt.
<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>
Chạy ví dụ »Ví dụ 2
Phần tử <p>
có màu nền riêng biệt khi 'nhập' và 'rời'
<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>
Chạy ví dụ »Ví dụ 3
Các phần tử <p>
được tạo hoạt ảnh khác nhau, sử dụng name
prop để phân biệt các thành phần <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>
Chạy ví dụ »Ví dụ 4
Sự kiện after-enter
sẽ kích hoạt phần tử <div>
được hiển thị.
<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>
Chạy ví dụ »Ví dụ 5
Nút chuyển đổi sẽ kích hoạt sự kiện 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>
Chạy ví dụ »Ví dụ 6
Prop appear
bắt đầu hoạt ảnh phần tử <p>
ngay sau khi trang được tải.
<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>
Chạy ví dụ »Ví dụ 7
Lật qua các hình ảnh có hoạt ảnh khi 'nhập' và 'rời'. Một hình ảnh mới được thêm vào trước khi hình ảnh cũ bị xóa.
<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>
Chạy ví dụ »Ví dụ 8
Lật qua các hình ảnh có hoạt ảnh khi 'nhập' và 'rời'. mode="out-in"
ngăn việc thêm hình ảnh mới cho đến khi xóa hình ảnh cũ.
<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>
Chạy ví dụ »Ví dụ 9
Chuyển đổi giữa các thành phần là hoạt hình.
<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>
Chạy ví dụ »Ví dụ 10
Chuyển đổi giữa các thành phần là hoạt hình.
<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>
Chạy ví dụ »Ví dụ 11
Sử dụng prop enterActiveClass
để đổi tên lớp CSS 'v-enter-active' thành '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>
Chạy ví dụ »Trang liên quan
Hướng dẫn Vue: Hoạt hình Vue
Hướng dẫn Vue: Vue Animations với v-for
Tham chiếu Vue: Thành phần Vue <TransitionGroup>