在 Vue 開發過程中,為應用添加過渡效果和處理響應式數據是提升用戶體驗和實現動態交互的關鍵。
一、transition:元素的單元素過渡效果
transition
是 Vue 提供的內置組件,專門用于為單個元素或組件添加過渡動畫。它會在元素插入、更新或移除 DOM 時自動應用相應的 CSS 類名,配合 CSS 動畫或過渡屬性,實現平滑的視覺效果。
1. 基本使用
使用transition
組件包裹需要添加過渡效果的元素,同時指定name
屬性,這個屬性值將作為 CSS 類名的前綴。示例代碼如下:
<template><div><button @click="show =!show">Toggle Element</button><transition name="fade"><p v-if="show">This is a paragraph with transition effect.</p></transition></div>
</template><script>
export default {data() {return {show: false};}
};
</script><style>
.fade-enter-active,
.fade-leave-active {transition: opacity 1s;
}
.fade-enter-from,
.fade-leave-to {opacity: 0;
}
</style>
在上述代碼中,當點擊按鈕時,<p>
元素會根據show
的值進行顯示或隱藏。transition
組件會在元素插入(顯示)和移除(隱藏)時,分別添加對應的 CSS 類名:
fade-enter-from
:進入過渡的起始狀態。fade-enter-active
:進入過渡的活躍狀態,應用過渡動畫。fade-enter-to
:進入過渡的結束狀態。fade-leave-from
:離開過渡的起始狀態。fade-leave-active
:離開過渡的活躍狀態,應用過渡動畫。fade-leave-to
:離開過渡的結束狀態。
transition過渡效果
2. 過渡模式
transition
還支持mode
屬性,用于指定過渡模式,解決元素切換時可能出現的閃爍問題。常見的過渡模式有:
in-out
:新元素先進行進入過渡,完成后當前元素進行離開過渡。out-in
:當前元素先進行離開過渡,完成后新元素進行進入過渡。
<transition name="slide" mode="out-in"><div v-if="show">{{ message }}</div>
</transition>
二、transition-group:多個元素的過渡效果
當需要對多個元素或組件同時添加過渡效果時,transition-group
就派上用場了。它與transition
的主要區別在于,transition-group
需要為每個子元素指定唯一的key
屬性,并且它會以真實的 DOM 元素形式渲染,而不是像transition
那樣作為一個不可見的包裹元素。
1. 基本使用
以下是一個簡單的列表項添加和移除過渡效果的示例:
<template><div><button @click="addItem">Add Item</button><transition-group name="slide" tag="ul"><li v-for="(item, index) in items" :key="index">{{ item }}</li></transition-group></div>
</template><script>
export default {data() {return {items: []};},methods: {addItem() {this.items.push(`Item ${this.items.length + 1}`);}}
};
</script><style>
.slide-enter-active,
.slide-leave-active {transition: all 0.5s;
}
.slide-enter-from,
.slide-leave-to {transform: translateX(100%);opacity: 0;
}
</style>
在這個例子中,每次點擊按鈕,新的列表項會以滑動的方式進入頁面,而移除列表項時也會有相應的滑動離開效果。tag
屬性指定了transition-group
最終渲染成的 HTML 標簽,這里設置為<ul>
。
transitionGroup過渡效果
2. 排序過渡
transition-group
還可以實現列表項排序時的過渡效果。當列表項順序發生變化時,通過監聽數據變化,結合sort
方法和過渡動畫,讓排序過程更加流暢。
<template><div><button @click="sortItems">Sort Items</button><!-- transition-group用于多個元素的過渡效果 --><!-- name="scale"指定過渡類名前綴,tag="ul"指定渲染為ul元素 --><transition-group name="scale" tag="ul"><!-- 使用對象的唯一ID作為key,確保Vue能正確跟蹤元素身份變化 --><!-- 當元素身份明確時,Vue才能正確應用進入/離開過渡 --><li v-for="item in sortedItems" :key="item.id">{{ item.value }}</li></transition-group></div>
</template><script>
export default {data() {return {// 使用對象數組,每個對象包含唯一ID和顯示值// 避免使用數組索引作為key,防止Vue復用相同位置的元素items: [{ id: 1, value: 'Apple' },{ id: 2, value: 'Banana' },{ id: 3, value: 'Cherry' },{ id: 4, value: 'Date' }],// 排序方向控制,用于確保每次點擊都有實際排序變化sortOrder: 'asc'};},computed: {sortedItems() {// 創建數組副本以觸發響應式更新// 使用localeCompare確保字符串按字母順序排序return [...this.items].sort((a, b) => {if (this.sortOrder === 'asc') {return a.value.localeCompare(b.value); // 升序排序} else {return b.value.localeCompare(a.value); // 降序排序}});}},methods: {async sortItems() {// 切換排序方向,確保每次點擊都有實際排序變化this.sortOrder = this.sortOrder === 'asc' ? 'desc' : 'asc';// 等待DOM更新完成// 確保上一次的排序操作已完全反映在DOM中await this.$nextTick();// 通過添加隨機延遲屬性強制Vue重新渲染元素// 這觸發了Vue的過渡系統,因為每個元素的屬性發生了變化this.items = this.sortedItems.map(item => ({...item,delay: Math.random() * 0.2 // 隨機延遲0-200ms}));// 注意:這里的delay屬性不需要在視圖中使用// 它僅用于觸發Vue的響應式系統和過渡效果}}
};
</script><style>
.scale-enter-active,
.scale-leave-active,
.scale-move {transition: all 0.5s;position: relative; /* 確保定位正確,防止過渡期間元素重疊 */
}
.scale-enter-from,
.scale-leave-to {transform: scale(0);opacity: 0;
}
</style>
在上述代碼中,點擊排序按鈕后,列表項在重新排序時會有縮放的過渡效果,scale-move
類名用于處理元素移動時的過渡動畫。
transitionGroup排序過渡效果
三、reactive:創建響應式對象
reactive
是 Vue 3 中用于創建響應式數據的函數。它接收一個普通對象作為參數,并返回一個響應式的代理對象。任何對代理對象屬性的修改都會觸發視圖的更新。
1. 基本使用
<template><div><p>Count: {{ state.count }}</p><button @click="increment">Increment</button></div>
</template><script>
import { reactive } from 'vue';export default {setup() {const state = reactive({count: 0});const increment = () => {state.count++;};return {state,increment};}
};
</script>
在setup
函數中,使用reactive
創建了一個包含count
屬性的響應式對象state
。當點擊按鈕調用increment
方法時,state.count
的值增加,視圖會自動更新顯示最新的計數。
2. 嵌套對象與數組
reactive
同樣適用于嵌套的對象和數組。對嵌套屬性的修改也會保持響應式。
<template><div><p>Name: {{ user.name }}</p><p>Age: {{ user.age }}</p><button @click="updateUser">Update User</button></div>
</template><script>
import { reactive } from 'vue';export default {setup() {const user = reactive({name: 'Alice',age: 25,address: {city: 'New York',street: '123 Main St'},hobbies: ['Reading', 'Music']});const updateUser = () => {user.name = 'Bob';user.age = 30;user.address.city = 'Los Angeles';user.hobbies.push('Traveling');};return {user,updateUser};}
};
</script>
在這個示例中,user
是一個包含嵌套對象和數組的響應式對象。調用updateUser
方法修改屬性時,相關的視圖內容都會及時更新。
四、ref:創建響應式引用
ref
是 Vue 3 中另一個重要的響應式 API,它可以用來創建一個包含任意類型值的響應式引用。與reactive
不同,ref
不僅適用于對象,還適用于基本數據類型(如字符串、數字、布爾值等)。
1. 基本使用
<template><div><p>Message: {{ message }}</p><button @click="changeMessage">Change Message</button></div></template><script>import { ref } from 'vue';export default {setup() {const message = ref('Hello, Vue!');const changeMessage = () => {message.value = 'Goodbye, Vue!';};return {message,changeMessage};}};</script>
在上述代碼中,使用ref
創建了一個包含字符串的響應式引用message
。在模板中通過message
顯示其值,點擊按鈕時修改message.value
,視圖會隨之更新。
2. 訪問 DOM 元素
ref
還常用于獲取 DOM 元素的引用。通過在模板元素上設置ref
屬性,并在setup
函數中使用同名的ref
,可以獲取到對應的 DOM 元素。
<template><div><input type="text" ref="inputElement" /><button @click="focusInput">Focus Input</button></div>
</template><script>
import { ref } from 'vue';export default {setup() {const inputElement = ref(null);const focusInput = () => {if (inputElement.value) {inputElement.value.focus();}};return {inputElement,focusInput};}
};
</script>
在上述代碼中,通過ref
獲取到<input>
元素的引用,點擊按鈕時調用focusInput
方法,將焦點設置到輸入框上。
在實際項目開發中,合理運用這些特性,可以為應用增添豐富的交互效果和高效的數據管理能力,提升用戶體驗。