Vue3 依赖注入 - Provide/Inject
对于父子组件通信,我们可以使用
props
来传递数据,但是对于多层级嵌套的组件,我们要向更深层的子组件传递数据,props
就完成不了。Vue3中提供了两个新的api,
provide()
和inject()
,就是用来解决跨代组件通信的问题。并且还可以向全局中注入数据。
provide()
向组件中注入数据,inject()
获取注入的数据。 一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第7天,点击查看活动详情。
1.基本使用
在父组件中注入数据:provide()
//父组件中注入
provide("key", "value");
子组件中获取数据:inject()
//子组件/隔代组件中获取
const inject1 = inject<string>("key");
2.注入响应式数据
provide()
能够注入任意的数据,当然也包括响应式数据。不同于props
的单向数据流,provide()
注入的是真的响应式数据。可以在父组件中修改,也可以在子组件中进行修改,都是响应式的,因为操作的都是同一个响应式对象。
父组件注入:
interface Person {
name: string,
age: number
}
const person: Person = reactive({
age: 18,
name: "tom"
})
provide<Person>("key", person)
//父组件修改数据
setTimeout(() => {
person.name = "cat";
},3000)
子组件获取:
const inject1 = inject<Person>("key");
//子组件修改数据
if (inject1 != undefined) {
inject1.name = "dog";
}
子组件的 inject1
和父组件的person
是同一个对象。
3. 使用 Symbol 作注入名
在项目中,会有非常多的注入数据,建议最好使用
Symbol
来作为注入的key
避免冲突。
定义:
新建一个keys.ts
文件,将要注入的key名
都在这个文件中进行定义,这样会便于我们管理和使用。
//keys.ts中
export interface Person {
name: string,
age: number
}
export const key = Symbol() as InjectionKey<Person>;//标注类型。
在定义的Symbol key
时使用Vue3提供的InjectionKey
接口来为注入的数据标记类型,这样在注入数据的时候,就能进行类型检查,在获取的时候返回的就是定义的类型,不用通过泛型去接受或者强转。
父组件中注入:
import {key, Person} from "./commonTs/keys";
const person: Person = reactive({
age: 18,
name: "tom"
});
provide(key, person)//在使用的时候会检查传入的类型。
子组件中获取:
import {key} from "../commonTs/keys";
const inject1 = inject(key);//获取的时候,返回的就是标识的类型。
因为使用InjectionKey
标记类型,返回值的类型就是key指定的类型,所有可以不用指定泛型来使用。
4. 注入全局数据
可以在
main.js
通过vue实例去注入全局的数据。是不是和Vuex很像?
main.js中注入:
import {key, Person} from "./commonTs/keys";
const app = createApp(App);
const person: Person = reactive({
age: 0,
name: "cat"
})
app.provide(key, person)
app.mount('#app');
组件中获取使用:
import {key} from "./commonTs/keys";
const inject1 = inject(key);
注意:注入的数据必须在实例挂载之前进行注,否则获取到的数据都是undefined
错误注入全局数据:
app.mount('#app');//实例挂载
app.provide(key, person)
正确注入全局数据:
app.provide(key, person)
app.mount('#app');