為什么要用組合式API呢
- 用原始方式寫,業(yè)務(wù)邏輯會過于分散;
- 使用組合式API,可以把同一業(yè)務(wù)邏輯的代碼放在一起;
使用組合式API寫代碼
1、所有邏輯都放在setup函數(shù),它的第一個參數(shù)是props對象(setup函數(shù)中的props是響應(yīng)式的,不能用ES6解構(gòu),會消除prop的響應(yīng)性)setup文檔
2、通過ref、reactive、toRef來創(chuàng)建響應(yīng)式數(shù)據(jù);
3、視圖要用到的變量、方法為setup函數(shù)返回的對象屬性;
4、watch、computed是個函數(shù);
5、生命周期鉤子寫法微調(diào),xyz變成onXyz,比如mounted變成onMounted,而且created和beforeCreate不再需要,這是因為setup函數(shù)本身就是圍繞created和beforeCreate來進(jìn)行的,所以不需要再定義它們,這兩個鉤子里編寫的任何代碼都直接寫在setup函數(shù)里即可;
setup函數(shù)中要使用
context.emit(context是setup的第二個參數(shù)),不能在setup函數(shù)里使用this.$emit,你可以在methods里使用this.$emit,但是我們以后在vue3中盡量不使用methods,要使用setup;
響應(yīng)式API
ref
- ref和reactive一樣, 也是用來實現(xiàn)響應(yīng)式數(shù)據(jù)的,不過它是傳遞一個簡單值
- ref底層的本質(zhì)其實還是reactive,系統(tǒng)會自動根據(jù)我們給ref傳入的值將它轉(zhuǎn)換成
ref(xx) -> reactive({value:xx}); - 在JS中我們要用
xx.value,但是在HTML模板中,直接使用xx
const count = ref(0)
console.log(count.value) // 0
count.value++
console.log(count.value) // 1
reactive
傳遞一個對象,把它變成響應(yīng)式數(shù)據(jù)(結(jié)合toRef代碼一起看)
toRef
為源響應(yīng)式對象上的某個 property 新創(chuàng)建一個 ref。然后,ref 可以被傳遞,它會保持對其源 property 的響應(yīng)式連接。
const state = reactive({
foo: 1,
bar: 2
})
const fooRef = toRef(state, 'foo')
fooRef.value++
console.log(state.foo) // 2
state.foo++
console.log(fooRef.value) // 3
toRefs
將響應(yīng)式對象轉(zhuǎn)換為普通對象,其中結(jié)果對象的每個 property 都是指向原始對象相應(yīng) property 的 ref;
一般用于setup參數(shù)props的結(jié)構(gòu)居多,比如:const {title} = toRefs(props)
const state = reactive({
foo: 1,
bar: 2
})
const stateAsRefs = toRefs(state)
/*
stateAsRefs 的類型:
{
foo: Ref<number>,
bar: Ref<number>
}
*/
// ref 和原始 property 已經(jīng)“鏈接”起來了
state.foo++
console.log(stateAsRefs.foo.value) // 2
stateAsRefs.foo.value++
console.log(state.foo) // 3

- 響應(yīng)式狀態(tài)解構(gòu)
import { reactive, toRefs } from 'vue'
const book = reactive({
author: 'Vue Team',
year: '2020',
title: 'Vue 3 Guide',
description: 'You are reading this book right now ;)',
price: 'free'
})
let { author, title } = toRefs(book)
title.value = 'Vue 3 Detailed Guide' // 我們需要使用 .value 作為標(biāo)題,現(xiàn)在是 ref
console.log(book.title) // 'Vue 3 Detailed Guide'
完整示例
<template>
有{{ count }}次
<button @click="onAddCount">click</button>
<h1>{{ helloText }}</h1>
</template>
<script>
import { onMounted, ref, computed, watch } from "vue";
function getData() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(Math.floor(Math.random() * 5));
}, 3000);
});
}
export default {
props: ["msg"],
setup(props) {
let count = ref(0);
const getCount = async () => {
count.value = await getData();
};
const onAddCount = () => {
count.value++;
};
onMounted(getCount);
let name = ref("win");
let helloText = computed(() => {
return props.msg + " " + name.value;
});
watch(count, (newvalue, oldvalue) => {
let result = "";
for (let i = 0; i < count.value; i++) {
result += name.value;
}
console.log(result, "result");
name.value = result;
});
return {
count,
onAddCount,
name,
helloText,
};
},
};
</script>