# 组合 API

本节使用单文件组件语法作为代码示例

# setup

在创建组件之前执行的一个组件选项,一旦 props 被解析,将作为 composition 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
1
2
3
4
5
6
7
8
9
10
11

提示

为了获得传递给 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' })
    
    			// 暴露给模板
    			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的value
    		return () => h('div', [readersNumber.value, book.title])
    	},
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
  • 参考Composition API setup

# 生命周期钩子函数

可以直接导入 onX 一族的函数来注册生命周期钩子:

import { onMounted, onUpdated, onUnmounted } from 'vue'

const MyComponent = {
	setup() {
		onMounted(() => {
			console.log('mounted!')
		})
		onUpdated(() => {
			console.log('updated!')
		})
		onUnmounted(() => {
			console.log('unmounted!')
		})
	},
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

这些生命周期钩子注册函数只能在 setup() 期间同步使用, 因为它们依赖于内部的全局状态来定位当前组件实例(正在调用setup() 的组件实例), 不在当前组件下调用这些函数会抛出一个错误。

组件实例上下文也是在生命周期钩子同步执行期间设置的,因此,在卸载组件时,在生命周期钩子内部同步创建的侦听器和计算状态也将自动删除。

  • 与选项 API 生命周期相对应的组合式 API

    • beforeCreate -> use setup()
    • created -> use setup()
    • beforeMount -> onBeforeMount
    • mounted -> onMounted
    • beforeUpdate -> onBeforeUpdate
    • updated -> onUpdated
    • beforeUnmount -> onBeforeUnmount
    • unmounted -> onUnmounted
    • errorCaptured -> onErrorCaptured
    • renderTracked -> onRenderTracked
    • renderTriggered -> onRenderTriggered
  • 参考: 组合 API 生命周期钩子函数

# Provide / Inject

provideinject 提供依赖注入。两者都只能在当前活动组件实例的 setup() 中调用。

  • 类型定义:
interface InjectionKey<T> extends Symbol {}

function provide<T>(key: InjectionKey<T> | string, value: T): void

// 未传,使用缺省值
function inject<T>(key: InjectionKey<T> | string): T | undefined
// 传入了默认值
function inject<T>(key: InjectionKey<T> | string, defaultValue: T): T
1
2
3
4
5
6
7
8

Vue 提供了一个继承 SymbolInjectionKey 接口。它可用于在提供者和消费者之间同步注入值的类型:

import { InjectionKey, provide, inject } from 'vue'

const key: InjectionKey<string> = Symbol()

provide(key, 'foo') // 类型不是 string 则会报错

const foo = inject(key) // foo 的类型: string | undefined
1
2
3
4
5
6
7

如果使用字符串作为键或没有定义类型的符号,则需要显式声明注入值的类型:

const foo = inject<string>('foo') // string | undefined
1