最近有小伙伴跟我聊起setup函數(shù),因?yàn)榱?xí)慣了vue2.x的寫法導(dǎo)致了岳枷,setup用起來覺得奇奇怪怪的芒填,在一些api混編的情況下,代碼變得更加混亂了空繁,個(gè)人覺得在工程化思想比較強(qiáng)的團(tuán)隊(duì)中使用setup確實(shí)能更好的使用模塊化開發(fā)殿衰,但是用得不好的話也確實(shí)降低了代碼的可讀性。本篇文章是從使用角度來聊聊setup的實(shí)際使用家厌。
setup 使用
1播玖、setup和以前的api(data,methods饭于,computed等)并不沖突蜀踏,也是可以相互訪問的,值得注意的是setup里面不能用this掰吕,并且在setup執(zhí)行的時(shí)候組件實(shí)例還未創(chuàng)建完畢果覆,故不也能使用data,methods殖熟,computed定義的變量和函數(shù)局待。如下混編示例:
import { getCurrentInstance} from 'vue'
setup() {
const count = 10; // 非響應(yīng)式的。
const { proxy } = getCurrentInstance(); // 這里 proxy 相當(dāng)于this
console.log(proxy.msg) // 不能在setup調(diào)用時(shí)訪問data里面的屬性
return {
count,
consoleMsg: () => {
console.log(proxy.msg) // 123菱属,點(diǎn)擊按鈕時(shí)可以訪問了
}
}
},
data() {
return {
msg: '123'
}
},
created() {
console.log(this.count) // 10钳榨,這時(shí)可以訪問setup拋出的屬性了。
}
2纽门、setup 還可以返回一個(gè)渲染函數(shù)薛耻,不過返回一個(gè)渲染函數(shù)將阻止我們返回任何其它的東西,當(dāng)我們想暴漏函數(shù)給其父組件使用的時(shí)候赏陵,可以使用expose來處理這個(gè)問題饼齿。示例如下:
import { h, ref } from 'vue'
export default {
setup(props, { expose }) {
const count = ref(0) // 創(chuàng)建一個(gè)響應(yīng)式的變量
const increment = () => ++count.value
expose({
increment
})
return () => h('div', count.value) // 請(qǐng)注意這里我們需要顯式使用 ref 的 value
}
}
看到這里就完全可以使用setup來做項(xiàng)目了饲漾,接下來就是封山開路遇水搭橋,碰到不會(huì)的就各種查缕溉,磕磕碰碰總能成功考传。然而一篇帖子不能寫到這里就結(jié)束了,后面還有一大堆相關(guān)的知識(shí)點(diǎn)呢证鸥。
響應(yīng)式
為什么聊響應(yīng)式呢僚楞,因?yàn)閟etup里面返回的變量雖然可以直接在模版語法中使用,但是它并不是響應(yīng)式的枉层,如上面第一個(gè)示例镜硕,我們?nèi)绻谀0嬷惺褂昧藍(lán){ count }}來展示count的值,然后我們改變count的值返干,值改變了,但是顯示不會(huì)變化血淌。
// 非響應(yīng)式示例矩欠,等價(jià)于錯(cuò)誤示例,請(qǐng)盡量不要復(fù)制這塊代碼到你項(xiàng)目中去了悠夯。
<template>
<div>
<span>{{ count }}</span>
<button @click="count ++; consoleValue(count)">Increment count</button>
</div>
</template>
<script>
export default {
setup() {
let count = 10; // 這里不是響應(yīng)式的癌淮。
return {
count,
consoleValue: (value) => {
console.log(value); // 這里值發(fā)生了變化
}
}
}
}
</script>
響應(yīng)式這塊在官網(wǎng)api比較多,只說幾個(gè)用得比較多的沦补。
1乳蓄、上面有提到的ref,ref 接收參數(shù)并將其包裹在一個(gè)帶有 value property 的對(duì)象中返回夕膀,然后可以使用該 property 訪問或更改響應(yīng)式變量的值虚倒。最簡單的例子,上面示例改成響應(yīng)式的产舞,如下:
<template>
<div>
<span>{{ count }}</span>
<button @click="count ++">Increment count</button>
<button @click="doubleCount">double count</button>
</div>
</template>
<script>
import { ref } from 'vue'
export default {
setup() {
let count = ref(10);
return {
count,
doubleCount: () => {
// 值得注意在setup里面需要使用.value來訪問
count.value *= 2;
}
}
}
}
</script>
2魂奥、reactive返回對(duì)象的響應(yīng)式副本。這個(gè)比較好理解易猫,跟以前2.x時(shí)代差別不大耻煤。
<template>
<div>
<span>{{ countObj.count }}</span>
<button @click="countObj.count ++">Increment count</button>
<button @click="doubleCount">double count</button>
</div>
</template>
<script>
import { reactive } from 'vue'
export default {
setup() {
const countObj = reactive({ count: 10 });
return {
countObj,
doubleCount: () => {
countObj.count *= 2;
}
}
}
}
</script>
3、toRef 和 toRefs 這兩個(gè)函數(shù)都是為了獲取一個(gè)響應(yīng)式的子項(xiàng)准颓,并且跟以前的響應(yīng)式數(shù)據(jù)進(jìn)行關(guān)聯(lián)
<template>
<div>
<div>{{ countObj.count }} {{countObj.changeTimes}}</div>
<div>{{ count }} {{ changeTimes }}</div>
<button @click="count ++; changeTimes ++">increment count</button>
<button @click="doubleCount">double count</button>
</div>
</template>
<script>
import { reactive, toRefs, toRef } from 'vue'
export default {
setup() {
const countObj = reactive({ count: 10, changeTimes: 0 });
const { count } = toRefs(countObj);
const changeTimes = toRef(countObj, 'changeTimes');
return {
countObj,
count,
changeTimes,
doubleCount: () => {
countObj.count *= 2;
changeTimes.value ++;
}
}
}
}
</script>
注意:toRefs 只會(huì)為源對(duì)象中包含的 property 生成 ref哈蝇。如果要為特定的 property 創(chuàng)建 ref,則應(yīng)當(dāng)使用toRef攘已,簡單粗暴的理解toRef可以給源對(duì)象添加一個(gè)關(guān)聯(lián)的響應(yīng)式屬性炮赦,如:(本想寫在上面示例中,不過感覺不清晰贯被,就單獨(dú)列了一塊偽代碼)
const countObj = reactive({ count: 10 });
const testV = toRef(countObj, 'test');
testV.value = 10;
console.log(countObj.test); // 10
setup 參數(shù)
使用 setup
函數(shù)時(shí)眼五,它將接收兩個(gè)參數(shù):
Props
setup
函數(shù)中的第一個(gè)參數(shù)是 props
妆艘。正如在一個(gè)標(biāo)準(zhǔn)組件中所期望的那樣,setup
函數(shù)中的 props
是響應(yīng)式的看幼,當(dāng)傳入新的 prop 時(shí)批旺,它將被更新。
export default {
props: {
title: String
},
setup(props) {
console.log(props.title)
}
}
但是诵姜,因?yàn)?props
是響應(yīng)式的汽煮,你不能使用 ES6 解構(gòu),它會(huì)消除 prop 的響應(yīng)性棚唆,上面說到的toRefs可以很好的解決這個(gè)問題暇赤。
import { toRefs } from 'vue'
setup(props) {
const { title } = toRefs(props)
console.log(title.value)
}
如果 title
是可選的 prop,則傳入的 props
中可能沒有 title
宵凌。在這種情況下鞋囊,toRefs
將不會(huì)為 title
創(chuàng)建一個(gè) ref 。你需要使用 toRef
替代它:
import { toRef } from 'vue'
setup(props) {
const title = toRef(props, 'title')
console.log(title.value)
}
Context
傳遞給 setup
函數(shù)的第二個(gè)參數(shù)是 context
瞎惫。context
是一個(gè)普通 JavaScript 對(duì)象溜腐,暴露了其它可能在 setup
中有用的值:
export default {
setup(props, context) {
// Attribute (非響應(yīng)式對(duì)象,等同于 $attrs)
console.log(context.attrs)
// 插槽 (非響應(yīng)式對(duì)象瓜喇,等同于 $slots)
console.log(context.slots)
// 觸發(fā)事件 (方法挺益,等同于 $emit)
console.log(context.emit)
// 暴露公共 property (函數(shù))
console.log(context.expose)
}
}
setup生命周期鉤子
在setup中可以訪問到以下生命周期鉤子:
- onBeforeMount
- onMounted
- onBeforeUpdate
- onUpdated
- onBeforeUnmount
- onUnmounted
- onErrorCaptured
- onRenderTracked
- onRenderTriggered
- onActivated
- onDeactivated
這些函數(shù)接受一個(gè)回調(diào)函數(shù),當(dāng)鉤子被組件調(diào)用時(shí)將會(huì)被執(zhí)行乘寒,如:
export default {
setup() {
// mounted
onMounted(() => {
console.log('Component is mounted!')
})
}
}
原創(chuàng)不易望众,轉(zhuǎn)載請(qǐng)注明出處,歡迎留言提議伞辛。