Provide/Inject
用途:在组件树中传递数据,避免 props层层传
定义
provide
function provide<T>(key: InjectionKey<T> | string, value: T): void
inject
// 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
// with factory
function inject<T>(
key: InjectionKey<T> | string,
defaultValue: () => T,
treatDefaultAsFactory: true
): T
一个不成熟的例子
父组件
provide('username', computed(() => form.username));
// provide('username', form.username)
// 如果这样传,子组件将会只得到初始值,后面值发生改变就不会同步
// 或者可以传递整个数据:provide('form', form);
任意下级组件
const username= inject('username');
这样我们可以通过 v-model 和 inject 直接在下层任意组件中绑定并修改值,但是官方不建议这样做。
When using reactive provide / inject values, it is recommended to keep any mutations to reactive state inside of the provider whenever possible. This ensures that the provided state and its possible mutations are co-located in the same component, making it easier to maintain in the future.
就是说建议只在provide组件中修改数据,这样做会让代码更好维护。
虽然用 v-model 很方便,但是官方说得对,为了让代码更好维护,可以在provide组件中,提供修改的方法,并provide。
于是这样写
父组件
const form= reactive<User>({
username: "rff",
// ...其他107个字段
});
const updateUsername = (v) => {
form.username= v;
};
// ...
下级任意子组件
<input v-model="username" />
const form = inject("form");
const updateUsername = inject("updateUsername");
const username = computed({
get: () => form.username,
set: updateUsername,
});
是的,这样看还好,但是如果变量多的话,就太太复杂了。
那这个“建议”要不。。?
参考:
Vue3 doc #定义
Vue3 doc #provide-inject
Vue3 doc #ts-provide-inject
Provide/Inject API With Vue 3