# 组合式 API
本节例子中代码使用的单文件组件语法
# setup
一个组件选项,在创建组件之前执行,一旦 props
被解析,并作为组合式 API 的入口点
入参:
{Data} props
{SetupContext} context
类型声明:
interface Data {
[key: string]: unknown
}
interface SetupContext {
attrs: Data
slots: Slots
emit: (event: string, ...args: unknown[]) => void
}
function setup(props: Data, context: SetupContext): Data
2
3
4
5
6
7
8
9
10
11
TIP
若要获取传递给 setup()
的参数的类型推断,请使用 defineComponent 是需要的。
示例:
使用模板:
<!-- MyBook.vue --> <template> <div>{{ readersNumber }} {{ book.title }}</div> </template> <script> import { ref, reactive } from 'vue' export default { setup() { const readersNumber = ref(0) const book = reactive({ title: 'Vue 3 Guide' }) // expose to template return { readersNumber, book } } } </script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21使用渲染函数:
// MyBook.vue import { h, ref, reactive } from 'vue' export default { setup() { const readersNumber = ref(0) const book = reactive({ title: 'Vue 3 Guide' }) // 请注意,我们需要在这里显式地暴露ref值 return () => h('div', [readersNumber.value, book.title]) } }
1
2
3
4
5
6
7
8
9
10
11
12
# 生命周期钩子
可以使用直接导入的 onX
函数注册生命周期钩子:
import { onMounted, onUpdated, onUnmounted } from 'vue'
const MyComponent = {
setup() {
onMounted(() => {
console.log('mounted!')
})
onUpdated(() => {
console.log('updated!')
})
onUnmounted(() => {
console.log('unmounted!')
})
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
这些生命周期钩子注册函数只能在 setup()
期间同步使用,因为它们依赖于内部全局状态来定位当前活动实例 (此时正在调用其 setup()
的组件实例)。在没有当前活动实例的情况下调用它们将导致错误。
组件实例上下文也是在生命周期钩子的同步执行期间设置的,因此在生命周期钩子内同步创建的侦听器和计算属性也会在组件卸载时自动删除。
选项 API 生命周期选项和组合式 API 之间的映射
-> usebeforeCreate
setup()
-> usecreated
setup()
beforeMount
->onBeforeMount
mounted
->onMounted
beforeUpdate
->onBeforeUpdate
updated
->onUpdated
beforeUnmount
->onBeforeUnmount
unmounted
->onUnmounted
errorCaptured
->onErrorCaptured
renderTracked
->onRenderTracked
renderTriggered
->onRenderTriggered
# Provide / Inject
provide
和 inject
启用依赖注入。只有在使用当前活动实例的 setup()
期间才能调用这两者。
- 类型声明:
interface InjectionKey<T> extends Symbol {}
function provide<T>(key: InjectionKey<T> | string, value: T): void
// without default value
function inject<T>(key: InjectionKey<T> | string): T | undefined
// with default value
function inject<T>(key: InjectionKey<T> | string, defaultValue: T): T
2
3
4
5
6
7
8
Vue 提供了一个 InjectionKey
接口,该接口是扩展 Symbol
的泛型类型。它可用于在提供者和消费者之间同步注入值的类型:
import { InjectionKey, provide, inject } from 'vue'
const key: InjectionKey<string> = Symbol()
provide(key, 'foo') // 提供非字符串值将导致错误
const foo = inject(key) // foo 的类型: string | undefined
2
3
4
5
6
7
如果使用字符串 key 或非类型化 symbols,则需要显式声明注入值的类型:
const foo = inject<string>('foo') // string | undefined
# getCurrentInstance
getCurrentInstance
enables access to an internal component instance useful for advanced usages or for library creators.
import { getCurrentInstance } from 'vue'
const MyComponent = {
setup() {
const internalInstance = getCurrentInstance()
internalInstance.appContext.config.globalProperties // access to globalProperties
}
}
2
3
4
5
6
7
8
9
getCurrentInstance
only works during setup or Lifecycle Hooks
When using outside of setup or Lifecycle Hooks, please call
getCurrentInstance()
onsetup
and use the instance instead.
const MyComponent = {
setup() {
const internalInstance = getCurrentInstance() // works
const id = useComponentId() // works
const handleClick = () => {
getCurrentInstance() // doesn't work
useComponentId() // doesn't work
internalInstance // works
}
onMounted(() => {
getCurrentInstance() // works
})
return () =>
h(
'button',
{
onClick: handleClick
},
`uid: ${id}`
)
}
}
// also works if called on a composable
function useComponentId() {
return getCurrentInstance().uid
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32