跳轉到內容

組合式API:setup()

基本用法

setup() 鉤子在以下情況下作為元件中組合式API使用的入口點:

  1. 在不進行構建步驟的情況下使用組合式API;
  2. 將基於組合式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 }) {
    ...
  }
}

attrsslots 是狀態物件,當元件本身更新時總是會被更新。這意味著您應該避免解構它們,並且始終以 attrs.xslots.x 的形式引用屬性。此外,與 props 不同,attrsslots 的屬性 不是 響應式的。如果您打算根據 attrsslots 的更改應用副作用,您應該在 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 方法將透過模板引用在父元件中可用。

組合式 API:setup() 已載入