props逐级透传问题:父组件向子组件传递数据时用props;如果父组件要传递数据给孙子组件,那么需要父组件props传递给子组件,子组件再把props传递给孙子组件;这样沿着组件链传递下去,非常麻烦。
provide和inject可以解决这一问题:一个父组件相对于其所有的后代组件,会作为依赖提供者。任何后代的组件树,无论层级有多深,都可以注入由父组件提供给整条链路的依赖。
-
provide(提供)
-
<script setup> import { provide } from 'vue'provide(/* 注入名 */ 'message', /* 值 */ 'hello!') </script>
-
provide()
函数接收两个参数。 -
第一个参数被称为注入名,可以是一个字符串或是一个
Symbol
。后代组件会用注入名来查找期望注入的值。一个组件可以多次调用provide()
,使用不同的注入名,注入不同的依赖值。 -
第二个参数是提供的值,值可以是任意类型,包括响应式的状态,比如一个 ref:
-
import { ref, provide } from 'vue'const count = ref(0) provide('key', count)
-
-
-
应用层provide
-
除了在一个组件中提供依赖,可以在整个应用层面提供依赖:
-
import { createApp } from 'vue' const app = createApp({}) app.provide(/* 注入名 */ 'message', /* 值 */ 'hello!')
-
在应用级别提供的数据在该应用内的所有组件中都可以注入。
-
-
Inject(注入)
-
要注入上层组件提供的数据,需使用 inject() 函数:
-
<script setup> import { inject } from 'vue'const message = inject('message') </script>
-
默认注入值
-
如果在注入一个值时不要求必须有提供者,那么我们应该声明一个默认值
-
// 如果没有祖先组件提供 "message" // `value` 会是 "这是默认值" const value = inject('message', '这是默认值')
-
-
-
和响应式数据配合使用
-
当提供 / 注入响应式的数据时,建议尽可能将任何对响应式状态的变更都保持在供给方组件中。这样可以确保所提供状态的声明和变更操作都内聚在同一个组件内,使其更容易维护。
-
<!-- 在供给方组件内 --> <script setup> import { provide, ref } from 'vue'const location = ref('North Pole')function updateLocation() {location.value = 'South Pole' }provide('location', {location,updateLocation }) </script>
-
<!-- 在注入方组件 --><template><button @click="updateLocation">{{ location }}</button> </template> <script setup> import { inject } from 'vue'const { location, updateLocation } = inject('location') </script>
-
最后,如果你想确保提供的数据不能被注入方的组件更改,你可以使用
readonly()
来包装提供的值。 -
<script setup> import { ref, provide, readonly } from 'vue'const count = ref(0) provide('read-only-count', readonly(count)) </script>
-
-
使用Symbol作为注入名
-
建议最好使用 Symbol 来作为注入名以避免潜在的冲突。
-
// keys.js export const myInjectionKey = Symbol()
-
// 在供给方组件中 import { provide } from 'vue' import { myInjectionKey } from './keys.js'provide(myInjectionKey, { /*要提供的数据 */ });
-
// 注入方组件 import { inject } from 'vue' import { myInjectionKey } from './keys.js'const injected = inject(myInjectionKey)
-