Vue Transition
竹白的 Vue.js 學習筆記
<transition>
也可以用在多個元素的轉場。
舉例來說:
<transition>
<table v-if="items.length > 0">
<!-- ... -->
</table>
<p v-else>Sorry, no items found.</p>
</transition>
但要注意,Vue 在切換畫面時,並不會完全置換元素,會使用一種最大限度減少動態元素並且儘可能的嘗試修復/再利用相同類型元素的算法。
因此當有相同標籤的元素在做切換時,需要使用 key
特性設置唯一的值來標記以讓 Vue 區分它們。
<transition>
<button v-if="isEditing" key="save">
Save
</button>
<button v-else key="edit">
Edit
</button>
</transition>
在一些場景中,也可以通過給同一個元素的 key 特性設置不同的狀態來代替 v-if
和 v-else
,上面的範例可以重寫為:
<transition>
<button v-bind:key="isEditing">
{{ isEditing ? 'Save' : 'Edit' }}
</button>
</transition>
使用多個 v-if
的多個元素的轉場可以重寫為綁定了動態屬性的單個元素轉場。例如:
<transition>
<button v-if="docState === 'saved'" key="saved">
Edit
</button>
<button v-if="docState === 'edited'" key="edited">
Save
</button>
<button v-if="docState === 'editing'" key="editing">
Cancel
</button>
</transition>
可以重寫為:
<!-- .html -->
<transition>
<button :key="docState">
{{ buttonMessage }}
</button>
</transition>
// ...
computed: {
buttonMessage: function () {
switch (this.docState) {
case 'saved': return 'Edit'
case 'edited': return 'Save'
case 'editing': return 'Cancel'
}
}
}
請考慮以下程式碼:
<transition>
<button :key="isEditing" @click="isEditing = !isEditing">
{{ isEditing ? 'On' : 'Off' }}
</button>
</transition>
在 on 按鈕和 off 按鈕的轉場中,兩個按鈕都被重繪了,一個離開轉場的時候另一個開始進入轉場。這是 <transition>
的預設行為,進入和離開同時發生。
你可能會想到,可以加上 position: absolute
,因為兩者重疊了,所以不會產生元素位移的情況:
button {
position: absolute;
}
但如果加上 translate
讓它們運動像滑動,還是會有兩個元素同時出現的破綻:
.v-enter,
.v-leave-to {
opacity: 0;
transform: translateX(100%);
}
同時生效的進入和離開的轉場不能滿足所有要求,所以 Vue 提供了轉場模式:
in-out
:新元素先進行轉場,完成之後當前元素轉場離開。out-in
:當前元素先進行轉場,完成之後新元素轉場進入。加上 mode="out-in"
的效果:
<transition mode="out-in">
<button :key="isEditing" @click="isEditing = !isEditing">
{{ isEditing ? 'On' : 'Off' }}
</button>
</transition>
.v-enter-active, .v-leave-active {
transition: 1.5s opacity;
}
in-out
模式的範例:
button {
position: absolute;
}
.v-enter,.v-leave-to {
opacity: 0;
}
.v-enter {
transform: translateX(100%);
}
.v-leave-to {
transform: translateX(-100%);
}
多個元件的轉場簡單很多,我們不需要使用 key
特性。只需要使用 動態切換 元件:
<!-- .html -->
<div id="app">
<input type="radio" value="v-a" v-model="view" />A
<input type="radio" value="v-b" v-model="view" />B
<transition name="component-fade" mode="out-in">
<component v-bind:is="view"></component>
</transition>
</div>
.component-fade-enter,
.component-fade-leave-to {
opacity: 0;
}
.component-fade-enter-active,
.component-fade-leave-active {
transition: opacity 0.3s ease;
}
const vm = new Vue({
el: '#app',
data: {
view: 'v-a',
},
components: {
'v-a': {
template: '<div>Component A</div>',
},
'v-b': {
template: '<div>Component B</div>',
},
},
});