這幾天整理的一下過往的文章和筆記,備份到了 Github 上,地址?? blog。
如果我的內(nèi)容幫助到了您,歡迎點個 Star ?????? 鼓勵鼓勵 :) ~~ ??
在 Composition API 中,我們沒有 this 與 Options API 中相同的引用。
在 Options API 中,我們可以調(diào)用 console.log(this) 的任何選項并獲得對組件本身的引用,讓我們可以訪問它的 props、computed、data 等。
Vue3 允許我們使用 Composition API,這些功能都位于 setup 函數(shù)內(nèi)。這意味著 setup 是我們聲明響應式數(shù)據(jù)、方法和計算屬性的地方。
import { ref } from 'vue'
export default {
props: {
lastName: String
},
setup() {
// 沒有 this,我們?nèi)绾问褂?props?
const createdMethod = () => {
console.log('created')
}
const name = ref('hello')
createdMethod()
return {
createdMethod,
name
}
}
}
setup 在我們的組件實例實際創(chuàng)建之前運行,并且由于我們的 setup 函數(shù)是我們實際上為組件定義所有內(nèi)容的地方,因此不再使用 this。
如何訪問組件屬性?
Composition API 為我們提供了訪問重要組件信息(如 props 和 slot)的替代方法。
setup 函數(shù)有參數(shù)讓我們訪問一些組件屬性:props 和 context。
-
props— 在我們的組件中包含定義的props -
context— 是一個 Javascript 對象,它公開了三個組件屬性
這三個屬性是:
-
context.attrs– 傳遞給我們組件的非props屬性 -
context.slots– 具有我們所有模板插槽渲染功能的對象 -
context.emit– 我們的組件發(fā)出事件的方法
讓我們更深入地了解其中的每一個。
context.attrs
假設我們有一個自定義組件,它接受一個名為 value 的 prop。
export default {
props: {
value: String,
},
setup(props, context) {
console.log(context.attrs)
}
}
然后在父組件中,我們向它傳遞幾個屬性。
<template>
<custom-component
:value="value"
test="hi"
@close="close"
/>
</template>
將打?。?/p>

可以看到,它包含除了我們聲明的 props 之外的所有內(nèi)容。這包括事件監(jiān)聽器和 HTML 屬性之類的東西。
這里的一個重要說明是 attrs 不是響應式的。這意味著如果我們想應用副作用來響應 attrs 值的變化,我們應該改用 onUpdated 生命周期鉤子。
context.slots
context.slots讓我們可以訪問每個 slot 的 render 方法。當我們編寫自己的自定義渲染函數(shù)而不使用模板代碼時,這很有用。
Vue 建議在大多數(shù)用例中使用模板,但如果你真的想使用 JavaScript 的全部功能,我們可以創(chuàng)建自己的渲染函數(shù)。
Vue 文檔中使用自定義 render 方法的一個很好的例子是,如果我們正在創(chuàng)建一個組件,該組件根據(jù) prop 的值渲染具有不同級別標題的插槽值。
<template>
<div>
<h1 v-if="level == 1">
<slot />
</h1>
<h2 v-if="level == 2">
<slot />
</h2>
<h3 v-if="level == 3">
<slot />
</h3>
<h4 v-if="level == 4">
<slot />
</h4>
<h5 v-if="level == 5">
<slot />
</h5>
<h6 v-if="level == 6">
<slot />
</h6>
</div>
</template>
<script>
export default {
props: {
level: Number
}
}
</script>
在這段代碼中,我們對所有 6 個標題選項使用 v-if 和 v-else-if 條件。正如您所看到的,有很多重復的代碼,而且看起來非?;靵y。
相反,我們可以使用 render 函數(shù)以編程方式生成我們的標題。使用 Composition API setup 函數(shù),它看起來像這樣。
import { h } from 'vue'
export default {
props: {
level: Number
},
setup(props, context) {
return () => h('h' + props.level, {})
}
}
但是,我們?nèi)绾巫屛覀兊牟宀圻M行渲染?
這就是 context.slots 發(fā)揮作用的地方。
通過讓我們訪問每個插槽的渲染函數(shù),我們可以輕松地將插槽添加到渲染函數(shù)中。每個插槽都可以通過其名稱訪問,并且由于我們沒有明確命名插槽,因此將其命名為 default。
import { h } from 'vue'
export default {
props: {
level: Number
},
setup(props, context) {
return () => h('h' + props.level, {}, context.slots.default())
}
}
現(xiàn)在,如果我們使用像這樣的簡單父組件來運行它
<template>
<child-component :level="1">
Hello World
</child-component>
</template>
這是我們完成的 DOM 的樣子。

因此,您可能不會經(jīng)常使用 context.slots,但是當您編寫復雜的 JavaScript 渲染函數(shù)時,它是一個強大的功能。
注意:根據(jù) Vue 文檔,
render函數(shù)的優(yōu)先級高于根據(jù)template選項或掛載元素的 DOM 內(nèi) HTML 模板編譯的渲染函數(shù)。
context.emit
context.emit 將替換 this.$emit 作為我們從組件發(fā)出事件的方式。
這對于向父組件發(fā)送任何類型的事件(帶或不帶數(shù)據(jù))非常有用。
假設我們有一個關閉按鈕,它發(fā)出一個名為 close 的事件。
<template>
<div>
<button @click="close">X</button>
</div>
</template>
<script>
export default {
setup (props, context) {
const close = () => {
context.emit('close')
}
return {
closeModal
}
}
}
</script>
然后在我們的父組件中,我們可以使用 v-on/@ 指令監(jiān)聽這個 close 事件。
<modal-component @close="handleClose" />
我們在 setup 中無權訪問什么
到目前為止,我們已經(jīng)看到了 Composition API 如何使我們能夠訪問四個不同的屬性:props、attrs、slots 和 emit。
但是由于 setup 在創(chuàng)建我們的組件實例之前運行,我們將無法訪問這三個組件屬性:
datacomputedmethods
例如,這些是我們在 setup 自身內(nèi)部聲明的屬性,但我們沒有內(nèi)置方法來訪問所有 data 屬性的列表。