Vue3新特性Composition?API實戰(zhàn)指南
前言
Vue3的發(fā)布標志著這個流行前端框架的重大升級。其中最引人注目的變化是引入了Composition API,它為開發(fā)者提供了一種全新的組織組件邏輯的方式。本文將深入探討Vue3的新特性,特別是Composition API的實際應用,幫助開發(fā)者掌握這一強大工具。
Vue3核心新特性概覽
Vue3相比Vue2有許多顯著的改進:
- 性能提升:重寫虛擬DOM實現(xiàn),渲染速度提升1.3~2倍,內(nèi)存占用減少一半
- Tree-shaking支持:更好的打包優(yōu)化,減小應用體積
- Composition API:全新的邏輯組織和復用方式
- Teleport組件:可以將內(nèi)容渲染到DOM樹的任何位置
- Fragments:組件可以有多個根節(jié)點
- Suspense:處理異步組件的新方式
- TypeScript支持:更完善的類型推斷
- 自定義渲染器API:更容易創(chuàng)建自定義渲染器
Composition API基礎
Composition API是Vue3最重要的特性之一,它提供了一種新的組織組件邏輯的方式。
基本結構
<script setup>
import { ref, computed, onMounted } from 'vue'
// 響應式狀態(tài)
const count = ref(0)
// 計算屬性
const doubleCount = computed(() => count.value * 2)
// 方法
function increment() {
count.value++
}
// 生命周期鉤子
onMounted(() => {
console.log('組件已掛載')
})
</script>
<template>
<div>
<p>計數(shù): {{ count }}</p>
<p>雙倍計數(shù): {{ doubleCount }}</p>
<button @click="increment">增加</button>
</div>
</template>
<script setup>語法
Vue3.2引入的<script setup>是使用Composition API的推薦方式,它具有以下優(yōu)勢:
- 更少的樣板代碼
- 變量和函數(shù)直接在模板中可用
- 更好的運行時性能
- 更好的IDE類型推斷
對比Options API與Composition API
Options API(Vue2的主要方式)
export default {
data() {
return {
count: 0
}
},
computed: {
doubleCount() {
return this.count * 2
}
},
methods: {
increment() {
this.count++
}
},
mounted() {
console.log('組件已掛載')
}
}
Composition API(Vue3推薦方式)
import { ref, computed, onMounted } from 'vue'
export default {
setup() {
const count = ref(0)
const doubleCount = computed(() => count.value * 2)
function increment() {
count.value++
}
onMounted(() => {
console.log('組件已掛載')
})
return {
count,
doubleCount,
increment
}
}
}
主要區(qū)別與優(yōu)勢
- 邏輯組織:Composition API按照邏輯關注點組織代碼,而非選項類型
- 邏輯復用:更容易提取和復用邏輯,沒有this的困擾
- 類型推斷:對TypeScript更友好
- 打包優(yōu)化:更好的Tree-shaking支持,減小應用體積
響應式系統(tǒng)
Vue3的響應式系統(tǒng)是完全重寫的,基于ES6的Proxy:
核心響應式API
- ref:處理基本類型的響應式數(shù)據(jù)
- reactive:處理對象類型的響應式數(shù)據(jù)
- computed:創(chuàng)建計算屬性
- watch/watchEffect:監(jiān)聽數(shù)據(jù)變化
import { ref, reactive, computed, watch, watchEffect } from 'vue'
// 基本類型的響應式
const count = ref(0)
console.log(count.value) // 訪問值需要.value
// 對象類型的響應式
const state = reactive({
name: '張三',
age: 25
})
console.log(state.name) // 直接訪問屬性
// 計算屬性
const doubleCount = computed(() => count.value * 2)
// 監(jiān)聽特定數(shù)據(jù)
watch(count, (newValue, oldValue) => {
console.log(`count從${oldValue}變?yōu)?{newValue}`)
})
// 自動追蹤依賴
watchEffect(() => {
console.log(`count: ${count.value}, name: ${state.name}`)
})
ref vs reactive
| ref | reactive | |
|---|---|---|
| 適用類型 | 任何類型 | 僅對象類型 |
| 訪問方式 | .value(模板中自動解包) | 直接訪問屬性 |
| 解構行為 | 保持響應性 | 失去響應性(需使用toRefs) |
| 使用場景 | 簡單值或需要解構時 | 復雜對象且不需解構時 |
生命周期鉤子
Composition API提供了一套新的生命周期鉤子:
| Options API | Composition API |
|---|---|
| beforeCreate | setup() |
| created | setup() |
| beforeMount | onBeforeMount |
| mounted | onMounted |
| beforeUpdate | onBeforeUpdate |
| updated | onUpdated |
| beforeUnmount | onBeforeUnmount |
| unmounted | onUnmounted |
| errorCaptured | onErrorCaptured |
import { onMounted, onBeforeUnmount } from 'vue'
export default {
setup() {
onMounted(() => {
console.log('組件已掛載')
})
onBeforeUnmount(() => {
console.log('組件即將卸載')
})
}
}
組合式函數(shù)(Composables)
Composition API最強大的特性之一是能夠輕松創(chuàng)建和使用可復用的組合式函數(shù)(Composables)。
創(chuàng)建一個組合式函數(shù)
// useCounter.js
import { ref, computed } from 'vue'
export function useCounter(initialValue = 0) {
const count = ref(initialValue)
const doubleCount = computed(() => count.value * 2)
function increment() {
count.value++
}
function decrement() {
count.value--
}
return {
count,
doubleCount,
increment,
decrement
}
}
使用組合式函數(shù)
<script setup>
import { useCounter } from './composables/useCounter'
const { count, doubleCount, increment, decrement } = useCounter(10)
</script>
<template>
<div>
<p>計數(shù): {{ count }}</p>
<p>雙倍計數(shù): {{ doubleCount }}</p>
<button @click="increment">增加</button>
<button @click="decrement">減少</button>
</div>
</template>
常用組合式函數(shù)示例
1. 使用鼠標位置
// useMouse.js
import { ref, onMounted, onUnmounted } from 'vue'
export function useMouse() {
const x = ref(0)
const y = ref(0)
function update(event) {
x.value = event.pageX
y.value = event.pageY
}
onMounted(() => window.addEventListener('mousemove', update))
onUnmounted(() => window.removeEventListener('mousemove', update))
return { x, y }
}
2. 使用本地存儲
// useLocalStorage.js
import { ref, watch } from 'vue'
export function useLocalStorage(key, defaultValue) {
const value = ref(JSON.parse(localStorage.getItem(key)) || defaultValue)
watch(value, val => {
localStorage.setItem(key, JSON.stringify(val))
})
return value
}
實戰(zhàn)案例:待辦事項應用
下面是一個使用Composition API構建的簡單待辦事項應用:
<script setup>
import { ref, computed } from 'vue'
import { useLocalStorage } from './composables/useLocalStorage'
// 使用本地存儲保存待辦事項
const todos = useLocalStorage('todos', [])
const newTodo = ref('')
// 計算屬性:未完成的待辦事項數(shù)量
const remaining = computed(() => {
return todos.value.filter(todo => !todo.completed).length
})
// 添加待辦事項
function addTodo() {
if (newTodo.value.trim()) {
todos.value.push({
id: Date.now(),
text: newTodo.value,
completed: false
})
newTodo.value = ''
}
}
// 刪除待辦事項
function removeTodo(id) {
todos.value = todos.value.filter(todo => todo.id !== id)
}
// 切換待辦事項完成狀態(tài)
function toggleTodo(id) {
const todo = todos.value.find(todo => todo.id === id)
if (todo) {
todo.completed = !todo.completed
}
}
</script>
<template>
<div class="todo-app">
<h1>待辦事項列表</h1>
<!-- 添加待辦事項 -->
<div class="add-todo">
<input
v-model="newTodo"
@keyup.enter="addTodo"
placeholder="添加新的待辦事項"
/>
<button @click="addTodo">添加</button>
</div>
<!-- 待辦事項列表 -->
<ul class="todo-list">
<li v-for="todo in todos" :key="todo.id" :class="{ completed: todo.completed }">
<input
type="checkbox"
:checked="todo.completed"
@change="toggleTodo(todo.id)"
/>
<span>{{ todo.text }}</span>
<button @click="removeTodo(todo.id)">刪除</button>
</li>
</ul>
<!-- 底部狀態(tài) -->
<div class="todo-footer" v-if="todos.length">
<span>{{ remaining }} 項待完成</span>
</div>
</div>
</template>
<style scoped>
.todo-app {
max-width: 500px;
margin: 0 auto;
padding: 20px;
font-family: Arial, sans-serif;
}
.add-todo {
display: flex;
margin-bottom: 20px;
}
.add-todo input {
flex-grow: 1;
padding: 8px;
border: 1px solid #ddd;
border-radius: 4px 0 0 4px;
}
.add-todo button {
padding: 8px 16px;
background-color: #4CAF50;
color: white;
border: none;
border-radius: 0 4px 4px 0;
cursor: pointer;
}
.todo-list {
list-style: none;
padding: 0;
}
.todo-list li {
display: flex;
align-items: center;
padding: 10px;
border-bottom: 1px solid #eee;
}
.todo-list li.completed span {
text-decoration: line-through;
color: #999;
}
.todo-list li span {
flex-grow: 1;
margin: 0 15px;
}
.todo-list li button {
background-color: #f44336;
color: white;
border: none;
padding: 5px 10px;
border-radius: 4px;
cursor: pointer;
}
.todo-footer {
margin-top: 20px;
color: #666;
}
</style>
性能優(yōu)化最佳實踐
使用Composition API時,需要注意一些性能優(yōu)化的最佳實踐:
1. 避免不必要的響應式轉換
// 不好的做法:創(chuàng)建不需要響應式的大型數(shù)據(jù)
const data = reactive(hugeData)
// 好的做法:僅對需要響應式的數(shù)據(jù)使用reactive或ref
const data = hugeData // 普通對象
const reactiveState = reactive({ count: 0 }) // 只對需要響應式的狀態(tài)使用reactive
2. 使用shallowRef和shallowReactive
對于大型對象,如果只需要跟蹤頂層屬性的變化:
import { shallowRef, shallowReactive } from 'vue'
// 只有.value的變更是響應式的,而不會深度追蹤
const state = shallowRef({ count: 0 })
// 只有頂層屬性的變更是響應式的
const user = shallowReactive({
name: '張三',
address: { city: '北京' } // 修改city不會觸發(fā)更新
})
3. 使用v-once和v-memo
<!-- 只渲染一次 -->
<div v-once>{{ expensiveComputation() }}</div>
<!-- 依賴項變化時才重新渲染 -->
<div v-memo="[item.id]">{{ item.name }}</div>
4. 合理使用計算屬性緩存
// 不好的做法:在方法中計算
function getFilteredItems() {
return items.value.filter(item => item.price > 100)
}
// 好的做法:使用計算屬性
const filteredItems = computed(() => {
return items.value.filter(item => item.price > 100)
})
總結與展望
Vue3的Composition API為我們提供了一種更靈活、更強大的組織組件邏輯的方式。它解決了Vue2中存在的許多問題,如邏輯復用困難、組件過于臃腫等。雖然學習曲線略陡,但一旦掌握,將極大提升開發(fā)效率和代碼質量。
隨著Vue生態(tài)系統(tǒng)的發(fā)展,我們可以期待更多基于Composition API的庫和工具,以及更多的最佳實踐和模式的出現(xiàn)。如果你還在使用Options API,不妨開始嘗試Composition API,體驗Vue3帶來的全新開發(fā)體驗。
以上就是Vue3新特性Composition API實戰(zhàn)指南的詳細內(nèi)容,更多關于Vue3 Composition API指南的資料請關注腳本之家其它相關文章!
相關文章
Vue中router.beforeEach與beforeRouteEnter的區(qū)別及說明
這篇文章主要介紹了Vue中router.beforeEach與beforeRouteEnter的區(qū)別及說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-10-10
Vue3中reactive變量重新賦值無法響應的3種處理方法
這篇文章主要給大家介紹了關于Vue3中reactive變量重新賦值無法響應的3種處理方法,在Vue3中可以使用reactive函數(shù)將一個普通對象轉換為響應式對象,需要的朋友可以參考下2023-08-08
Vue使用sign-canvas實現(xiàn)在線手寫簽名的實例
sign-canvas?一個基于?canvas?開發(fā),封裝于?Vue?組件的通用手寫簽名板(電子簽名板),支持?pc?端和移動端,本文給大家分享Vue使用sign-canvas實現(xiàn)在線手寫簽名,感興趣的朋友一起看看吧2022-05-05
vue中實現(xiàn)methods一個方法調(diào)用另外一個方法
下面小編就為大家分享一篇vue中實現(xiàn)methods一個方法調(diào)用另外一個方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-02-02
Vue 中文本內(nèi)容超出規(guī)定行數(shù)后展開收起的處理的實現(xiàn)方法
這篇文章主要介紹了Vue 中文本內(nèi)容超出規(guī)定行數(shù)后展開收起的處理的實現(xiàn)方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-04-04
vue.js中v-on:textInput無法執(zhí)行事件問題的解決過程
大家都知道vue.js通過v-on完成事件處理與綁定,但最近使用v-on的時候遇到了一個問題,所以下面這篇文章主要給大家介紹了關于vue.js中v-on:textInput無法執(zhí)行事件問題的解決過程,需要的朋友可以參考下。2017-07-07
Vuex中的getter和mutation的區(qū)別詳解
在現(xiàn)代前端開發(fā)中,狀態(tài)管理是一個不可忽視的話題,而Vuex作為Vue.js的官方狀態(tài)管理庫,在大型應用中扮演著至關重要的角色,當我們使用Vuex進行狀態(tài)管理時,getter和mutation是兩個重要的概念,在本文中,我們將詳細探討getter和mutation的區(qū)別,需要的朋友可以參考下2024-12-12

