這邊就像寫css一樣,只是要漸變的東西包在transition
裡面,並到css下樣式。
<div style="height:120px">
<transition>
<div class="block" v-show="isShow">Hello</div>
</transition>
</div>
<button @click="isShow=!isShow">Toggle</button>
const app = Vue.createApp({
data() {
return {
isShow: true
}
}
});
.block {
display: block;
width: 150px;
height: 100px;
text-align: center;
line-height: 100px;
background-color: palevioletred;
}
.v-enter-active,
.v-leave-active {
transition: opacity 1s;
}
.v-enter-from,
.v-leave-to {
opacity: 0;
}
.v-enter-to,
.v-leave-from {
opacity: 1;
}
賦予name
,把css中v-
開頭改成和name
一樣就可以自訂多個不同的效果
<transition name="fade">
<div class="block" v-show="isShow">Hello</div>
</transition>
.fade-enter-active,
.fade-leave-active {
transition: opacity 1s;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
}
.fade-enter-to,
.fade-leave-from {
opacity: 1;
}
繼上面的範例加上v-if
和v-else
就可以做條件的動態切換。
<div style="height:120px">
<transition name="fade">
<div class="block" v-if="isShow">no1</div>
<div class="block" v-else>no2</div>
</transition>
</div>
<button @click="isShow=!isShow">Toggle</button>
在transition
中加上mode
屬性
<transition name="fade" mode="in-out">
<div class="block" v-if="isShow">no1</div>
<div class="block" v-else>no2</div>
</transition>
若使用多個v-if
就需要使用transition-group,兩個不一樣的地方就是內容物必須加入唯一值key
才能正常動畫且不支援mode
。
<div class="mode">
<label>
<input v-model="demo" type="radio" value='A'>block A
</label>
<label>
<input v-model="demo" type="radio" value='B'>block B
</label>
<label>
<input v-model="demo" type="radio" value='C'>block C
</label>
</div>
<transition-group name="fade">
<div v-if="demo==='A'" :key="block-a" class="block">A block</div>
<div v-if="demo==='B'" :key="block-b" class="block">B block</div>
<div v-if="demo==='C'" :key="block-c" class="block">C block</div>
</transition-group>
const app = Vue.createApp({
data() {
return {
demo: 'A',
isShow: true
}
}
});
transition-group
最常與v-for
搭配尤其是列表顯示,範例中的tag
屬性可以指定最外層由誰包覆。
<button @click="add">Generate a random number</button>
<button @click="list.length=0">Remove all</button>
<transition-group tag="ul" class="number-list" name="list">
<li v-for="(item,index) in list" :key="index" class="item">{{item}}</li>
</transition-group>
const app = Vue.createApp({
data() {
return {
list: [1, 2, 3, 4, 5]
}
},
methods: {
add() {
const randomNumber = Math.ceil(Math.random() * 100 + 1)
this.list.push(randomNumber)
}
}
});
#app {
position: relative;
display: block;
padding: 1rem;
font-size: 1rem;
}
button {
font-size: 1rem;
margin-bottom: 1rem;
margin-right: 1rem;
}
.number-list {
overflow: hidden;
padding: 0;
margin-bottom: 1.5rem;
}
.number-list>li {
display: block;
float: left;
width: 35px;
height: 35px;
text-align: center;
line-height: 35px;
background-color: #f00;
color: #fff;
margin-right: 1rem;
margin-left: 0;
margin-bottom: 1rem;
}
.list-enter-active,
.list-leave-active,
.list-move {
transition: opacity 0.7s, transform 0.7s;
}
/*按remove時會回到最左邊淡出*/
.list-leave-active {
position: absolute;
}
.list-enter-from {
opacity: 0;
transform: translateY(-20px);
}
.list-leave-to {
opacity: 0;
transform: translateY(20px);
}
除了上面漸變的class外,還有新增一個v-move
,當元素改變定位時進行的動畫。
<button @click="add">Add</button>
<button @click="shuffle">Shuffle</button>
<transition-group tag="ul" class="number-list" name="list">
<li v-for="(item,index) in list" :key="item" class="item">{{item}}</li>
</transition-group>
const app = Vue.createApp({
data() {
return {
list: [1, 2, 3, 4, 5, 6, 7, 8, 9],
nextNum: 10
}
},
methods: {
randomIndex() {
return Math.floor(Math.random() * this.list.length)
},
add() {
this.list.splice(this.randomIndex(), 0, this.nextNum++)
},
shuffle() {
this.list.sort(() => Math.random() - 0.5)
}
}
});
.list-move {
transition: all 5s ease
}