Vue 3.x 的全面升級引入了 Composition API胰柑,這是對 Vue 2.x 傳統(tǒng) Options API 的一個重大改進峦树,它提供了更加靈活和模塊化的代碼組織方式.
Composition API的核心概念和函數(shù)
setup()函數(shù):
Vue 3 中的核心入口辣辫,用于設(shè)置組件的狀態(tài)和邏輯,它在 beforeCreate 鉤子之后魁巩,create 鉤子之前執(zhí)行。代替了原本在 data姐浮、methods 等選項中定義的內(nèi)容谷遂。
import { ref, computed } from 'vue';
export default {
setup() {
// 響應(yīng)式數(shù)據(jù)
const count = ref(0);
// 計算屬性
const doubleCount = computed(() => count.value * 2);
// 方法
function increment() {
count.value++;
}
// 返回需要在模板中使用的數(shù)據(jù)和方法
return {
count,
doubleCount,
increment
};
}
};
ref 和 reactive:
用于創(chuàng)建響應(yīng)式數(shù)據(jù),ref
用于創(chuàng)建基本類型的響應(yīng)式數(shù)據(jù)卖鲤,reactive
用于對象和數(shù)組的響應(yīng)式代理肾扰。
import { ref, reactive } from 'vue';
export default {
setup() {
// 使用ref創(chuàng)建響應(yīng)式基本類型
const count = ref(0);
// 使用reactive創(chuàng)建響應(yīng)式對象
const user = reactive({
name: 'Alice',
age: 30
});
// 修改響應(yīng)式數(shù)據(jù)
count.value++;
user.age++;
return { count, user };
}
};
計算屬性與偵聽器:
computed
用于創(chuàng)建計算屬性,只有當(dāng)依賴發(fā)生變化時才會重新計算蛋逾。
import { ref, computed } from 'vue';
export default {
setup() {
const firstName = ref('John');
const lastName = ref('Doe');
// 計算全名
const fullName = computed(() => `${firstName.value} ${lastName.value}`);
return { firstName, lastName, fullName };
}
};
watch 用于觀察響應(yīng)式數(shù)據(jù)的變化集晚,并在變化時執(zhí)行回調(diào)。
import { ref, watch } from 'vue';
export default {
setup() {
const count = ref(0);
// 觀察count變化
watch(count, (newVal, oldVal) => {
console.log(`count changed from ${oldVal} to ${newVal}`);
});
function increment() {
count.value++;
}
return { count, increment };
}
};
組合函數(shù)
Composition API鼓勵創(chuàng)建可復(fù)用的組合函數(shù)区匣。
// useCounter.js
export function useCounter(initialValue = 0) {
const count = ref(initialValue);
function increment() {
count.value++;
}
return { count, increment };
}
// 在組件中使用
import { useCounter } from './useCounter';
export default {
setup() {
const { count, increment } = useCounter(10);
return { count, increment };
}
};
生命周期鉤子:
Vue 3 中的生命周期鉤子不再直接在 setup() 內(nèi)部使用偷拔,而是通過 onBeforeMount、onMounted 等新的生命周期鉤子函數(shù)亏钩。
1. onBeforeMount: 此鉤子在組件掛載到DOM之前被調(diào)用莲绰。這類似于Vue 2.x中的 beforeMount
生命周期鉤子。
import { onBeforeMount } from 'vue';
export default {
setup() {
onBeforeMount(() => {
console.log('組件即將掛載');
});
}
};
2. onMounted: 當(dāng)組件被掛載到DOM上后立即調(diào)用姑丑。相當(dāng)于Vue 2.x的 mounted
蛤签。
import { onMounted } from 'vue';
export default {
setup() {
onMounted(() => {
console.log('組件已掛載');
});
}
};
3. onBeforeUpdate: 在組件數(shù)據(jù)變化導(dǎo)致的更新之前調(diào)用,但還未開始DOM更新栅哀。類似于Vue 2.x的 beforeUpdate
震肮。
import { onBeforeUpdate } from 'vue';
export default {
setup() {
let previousData;
onBeforeUpdate(() => {
console.log('數(shù)據(jù)更新前:', previousData);
});
return { data };
}
};
4. onUpdated: 組件數(shù)據(jù)變化導(dǎo)致的DOM更新完成后調(diào)用。相當(dāng)于Vue 2.x的 updated留拾。
import { onUpdated } from 'vue';
export default {
setup() {
onUpdated(() => {
console.log('組件更新完成');
});
}
};
5. onBeforeUnmount: 組件卸載之前調(diào)用戳晌。類似于Vue 2.x的 beforeDestroy。
import { onBeforeUnmount } from 'vue';
export default {
setup() {
onBeforeUnmount(() => {
console.log('組件即將卸載');
});
}
};
6. onUnmounted: 組件已經(jīng)被卸載后調(diào)用间驮。相當(dāng)于Vue 2.x的 destroyed躬厌。
import { onUnmounted } from 'vue';
export default {
setup() {
onUnmounted(() => {
console.log('組件已卸載');
});
}
};
7. onActivated: 僅在使用 <keep-alive>
包裹的組件激活時調(diào)用。
import { onActivated } from 'vue';
export default {
setup() {
onActivated(() => {
console.log('組件被激活');
});
}
};
8. onDeactivated: 僅在使用 <keep-alive>
包裹的組件停用時調(diào)用竞帽。
import { onDeactivated } from 'vue';
export default {
setup() {
onDeactivated(() => {
console.log('組件被停用');
});
}
};
Composition API編寫組件
- 創(chuàng)建響應(yīng)式數(shù)據(jù):使用 ref 和 reactive 創(chuàng)建響應(yīng)式變量扛施。
- 計算屬性:使用 computed 函數(shù)創(chuàng)建計算屬性。
- 響應(yīng)式函數(shù):使用 toRefs() 和 toRef() 轉(zhuǎn)換對象屬性為響應(yīng)式屹篓。
- 監(jiān)聽器:使用 watch 或 watchEffect 監(jiān)聽數(shù)據(jù)變化疙渣。
import { ref, reactive, computed, toRefs, watch } from 'vue';
import axios from 'axios';
export default {
setup() {
// 創(chuàng)建響應(yīng)式數(shù)據(jù)
const state = reactive({
cityInput: '',
city: '',
weather: null
});
// 計算屬性,直接返回輸入的城市名稱
const currentCity = computed(() => state.cityInput);
// 將state對象的屬性轉(zhuǎn)化為響應(yīng)式引用
const { cityInput } = toRefs(state);
// 響應(yīng)式函數(shù)堆巧,用于處理API請求
const fetchWeather = async () => {
if (!cityInput.value.trim()) return;
try {
const response = await axios.get(`https://api.weatherapi.com/v1/current.json?key=YOUR_API_KEY&q=${cityInput.value}`);
state.city = response.data.location.name;
state.weather = { temp: response.data.current.temp_c };
} catch (error) {
console.error('獲取天氣信息失敗', error);
}
};
// 監(jiān)聽器妄荔,監(jiān)聽城市輸入變化泼菌,清空天氣信息
watch(cityInput, () => {
state.weather = null;
});
// 返回暴露給模板的變量和方法
return {
cityInput,
currentCity,
fetchWeather
};
}
};
創(chuàng)建響應(yīng)式數(shù)據(jù):使用
reactive
創(chuàng)建了一個包含cityInput
、city
和weather
的響應(yīng)式對象啦租。ref
也可以用于基本類型的響應(yīng)式數(shù)據(jù)哗伯,但在這個場景下,reactive
更適合管理多個狀態(tài)篷角。計算屬性:
currentCity
計算屬性直接返回state.cityInput
的值焊刹,雖然在這個例子中直接使用v-model="cityInput"
可能更直觀,但展示了如何定義計算屬性恳蹲。響應(yīng)式函數(shù): 使用
toRefs
將state
對象的屬性轉(zhuǎn)化為獨立的響應(yīng)式引用虐块,便于在模板中直接綁定。這里主要展示了響應(yīng)式數(shù)據(jù)的使用嘉蕾,而不是轉(zhuǎn)換函數(shù)本身贺奠,因為直接使用解構(gòu)賦值(如const { cityInput } = state;
)在模板中已經(jīng)足夠。監(jiān)聽器: 使用
watch
監(jiān)聽cityInput
的變化错忱,每次輸入變化時清除weather
狀態(tài)儡率,以便于下次查詢。
從Options API遷移到Composition API
組件結(jié)構(gòu)
將狀態(tài)航背、方法和邏輯分離到單獨的函數(shù)中喉悴。在Options API中,我們通常在組件選項中定義data玖媚、methods箕肃、computed等。而在Composition API中今魔,這些邏輯被分離到單獨的函數(shù)中勺像。例如:
Options API:
export default {
data() {
return {
message: 'Hello, Vue!'
};
},
methods: {
greet() {
console.log(this.message);
}
},
computed: {
reversedMessage() {
return this.message.split('').reverse().join('');
}
}
};
Composition API:
import { ref, computed } from 'vue';
export default {
setup() {
const message = ref('Hello, Vue!');
function greet() {
console.log(message.value);
}
const reversedMessage = computed(() => message.value.split('').reverse().join(''));
return {
message,
greet,
reversedMessage
};
}
};
依賴注入
使用 provide 和 inject。在Options API中错森,我們使用provide和inject來傳遞數(shù)據(jù)吟宦。在Composition API中,這個過程保持不變:
Options API:
// 父組件
export default {
provide() {
return {
parentValue: '父組件的值'
};
}
};
// 子組件
export default {
inject: ['parentValue'],
mounted() {
console.log(this.parentValue); // 輸出 "父組件的值"
}
};
Composition API:
// 父組件
export default {
setup() {
provide('parentValue', '父組件的值');
}
};
// 子組件
export default {
setup(_, { inject }) {
const parentValue = inject('parentValue');
onMounted(() => {
console.log(parentValue); // 輸出 "父組件的值"
});
}
};
模板重構(gòu)
將綁定的屬性和方法從 this 轉(zhuǎn)換為直接引用涩维。