外觀
組合式API:setup()
基本用法
setup() 鉤子在以下情況下作為元件中組合式API使用的入口點:
- 在不進行構建步驟的情況下使用組合式API;
- 將基於組合式API的程式碼整合到選項API元件中。
注意
如果您使用組合式API與單檔案元件,強烈推薦使用 <script setup> 以獲得更簡潔、更直觀的語法。
我們可以使用 響應性API 宣告響應式狀態,並透過從 setup() 返回一個物件將其暴露給模板。返回物件上的屬性也將作為元件例項上的屬性提供(如果使用了其他選項)
vue
<script>
import { ref } from 'vue'
export default {
setup() {
const count = ref(0)
// expose to template and other options API hooks
return {
count
}
},
mounted() {
console.log(this.count) // 0
}
}
</script>
<template>
<button @click="count++">{{ count }}</button>
</template>從 setup 返回的 refs 在模板中訪問時將自動淺解包,因此您在訪問它們時不需要使用 .value。當在 this 上訪問時,它們也會以相同的方式解包。
setup() 本身無法訪問元件例項 - 在 setup() 內部,this 的值將是 undefined。您可以從選項API訪問組合式API公開的值,但不能反向操作。
setup() 應該同步返回一個物件。唯一可以使用 async setup() 的情況是當元件是 Suspense 元件的子元件時。
訪問屬性
在 setup 函式中的第一個引數是 props 引數。正如您在標準組件中預期的那樣,在 setup 函式內部的 props 是響應式的,並且當傳入新的屬性時將會更新。
js
export default {
props: {
title: String
},
setup(props) {
console.log(props.title)
}
}請注意,如果您解構了 props 物件,解構的變數將失去響應性。因此,建議始終以 props.xxx 的形式訪問屬性。
如果您確實需要解構屬性,或者需要在保持響應性的同時將屬性傳遞給外部函式,可以使用 toRefs() 和 toRef() 工具 API 來實現。
js
import { toRefs, toRef } from 'vue'
export default {
setup(props) {
// turn `props` into an object of refs, then destructure
const { title } = toRefs(props)
// `title` is a ref that tracks `props.title`
console.log(title.value)
// OR, turn a single property on `props` into a ref
const title = toRef(props, 'title')
}
}設定上下文
傳遞給 setup 函式的第二個引數是 設定上下文 物件。該上下文物件公開了在 setup 內可能有用的其他值。
js
export default {
setup(props, context) {
// Attributes (Non-reactive object, equivalent to $attrs)
console.log(context.attrs)
// Slots (Non-reactive object, equivalent to $slots)
console.log(context.slots)
// Emit events (Function, equivalent to $emit)
console.log(context.emit)
// Expose public properties (Function)
console.log(context.expose)
}
}上下文物件不是響應式的,可以安全地解構。
js
export default {
setup(props, { attrs, slots, emit, expose }) {
...
}
}attrs 和 slots 是狀態物件,當元件本身更新時總是會被更新。這意味著您應該避免解構它們,並且始終以 attrs.x 或 slots.x 的形式引用屬性。此外,與 props 不同,attrs 和 slots 的屬性 不是 響應式的。如果您打算根據 attrs 或 slots 的更改應用副作用,您應該在 onBeforeUpdate 生命週期鉤子內部這樣做。
公開公共屬性
expose 是一個函式,可以用來顯式限制當元件例項透過 模板引用 由父元件訪問時暴露的屬性。
js
export default {
setup(props, { expose }) {
// make the instance "closed" -
// i.e. do not expose anything to the parent
expose()
const publicCount = ref(0)
const privateCount = ref(0)
// selectively expose local state
expose({ count: publicCount })
}
}與渲染函式一起使用
setup 還可以返回一個 渲染函式,該函式可以直接使用同一作用域中宣告的響應式狀態。
js
import { h, ref } from 'vue'
export default {
setup() {
const count = ref(0)
return () => h('div', count.value)
}
}返回渲染函式會阻止我們返回其他任何內容。從內部來看,這不應該是個問題,但如果我們想要透過模板引用將此元件的方法暴露給父元件,可能會出現問題。
我們可以透過呼叫 expose() 來解決這個問題。
js
import { h, ref } from 'vue'
export default {
setup(props, { expose }) {
const count = ref(0)
const increment = () => ++count.value
expose({
increment
})
return () => h('div', count.value)
}
}然後,increment 方法將透過模板引用在父元件中可用。