provide/inject 依赖注入

依赖注入

在我们日常开发的过程中,我们需要从父组件向子组件传递数据,会使用 props

如果组件层级过多,使用 props 沿着组件链逐级传递下去,十分的麻烦。

而在 Vue 中使用 provideinject 来帮助我们解决这一问题。

父组件可以为其所有的后代组件提供依赖,无论层级有多深。

import { provide, inject } from "vue";

provide

provide 可以提供一个值,可以被后代组件注入,它是一个后代组件依赖的提供者。

// parent.vue
import { provide } from "vue";

provide("data", {
  name: "Buerjia",
  age: 23,
});

inject

inject 用于声明 provide 提供的依赖。

// chlid.vue
import { inject } from "vue";
const data = inject("data");

console.log(data);
// log
// { name: "Buerjia", age: 23 }

当父组件没有传入提供给我们相关依赖的情况下,我们还可以为 inject 设置默认值。

// chlid.vue
import { inject } from "vue";
const data = inject("data", {
  name: "jack",
  age: 24,
});

console.log(data);
// log
// { name: "jack", age: 24 }

思考?

在多人协作开发的项目中,我们很难确保 provide 提供的 key 保持唯一性,那么我们可以这么去解决它呢?

使用 Symbol 作为注入名

我们都知道 es6 中给我们提供了一个新的数据类型 Symbol ,代表着独一无二的值,我们可以将 Symbol 作为 key 值来比避免谈对协作中的命名冲突。

// ./injectionSymbols.ts

export const dataSymbol = Symbol();
// parent.vue
import { provide } from "vue";
import { dataSymbol } from "./injectionSymbols";

provide(dataSymbol, {
  name: "Buerjia",
  age: 23,
});
// child.vue
import { inject } from "vue";
import { dataSymbol } from "../injectionSymbols";

const data = inject(dataSymbol, {
  name: "jack",
  age: 24,
});

响应式的数据注入

provide 提供的数据本身就是响应式的,我们只需要修改 provide 提供的数即可。

// parent.vue
import { ref, provide } from "vue";
import { dataSymbol } from "../injectionSymbols";
import { dataRaw } from "../types/inject";

const data = ref<dataRaw>({
  name: "",
  age: 18,
});

provide(dataSymbol, data.value);

setTimeout(() => {
  data.value.name = "Mary";
}, 3000);

当我在我们日常的业务场景中我们不仅仅通过父组件去更新状态,我们还需要通过子组件去更新状态。

Vue 的官方推荐我们在创建 provide 的时候暴露给 inject 修改的状态的的方法。

// parent.vue
import { ref, provide } from "vue";
import { dataSymbol } from "../injectionSymbols";
import { dataRaw } from "../types/inject";

const data = ref<dataRaw>({
  name: "Buerjia",
  age: 18,
});

const updateData = (name: string) => {
  data.value.name = name;
};

provide(dataSymbol, {
  data: data.value,
  updateData,
});
// child.vue
import { inject } from "vue";
import { dataSymbol } from "../injectionSymbols";

const { data, updateData } = inject(dataSymbol, {
  data: {
    name: "Jack",
    age: 24,
  },
});

setTimeout(() => {
  updateData && updateData("Mary");
}, 3000);

当然有些时候我们并不希望我们的数据被改变,我们使用使用 readonly() 来包装,当我们尝试修改时将会失败。

// parent.vue
import { ref, provide, readonly } from "vue";
import { dataSymbol } from "../injectionSymbols";
import { dataRaw } from "../types/inject";

const data = ref<dataRaw>({
  name: "Buerjia",
  age: 18,
});

provide(dataSymbol, readonly(data.value));
// child.vue
import { inject } from "vue";
import { dataSymbol } from "../injectionSymbols";

const data = inject(dataSymbol, {
  name: "Jack",
  age: 24,
});

data.name = "Mary";
// [Vue warn] Set operation on key "name" failed: target is readonly.

为 provide/inject 添加类型

provideinject 通常在不同组件中运行,所以我们需要为其添加类型支持。

Vue 为我们提供了 InjectionKey 的类型接口,可以 provideinject 中同步注入值的类型。

import { InjectionKey } from "vue";
import { dataRaw } from "./types/inject";

export const dataSymbol = Symbol() as InjectionKey<dataRaw>;

总结

provide/inject 依赖注入相比 props,极大的减少了依赖嵌套,使得代码更加的简洁并且利于维护,日常开发中要思考多加思考是否能够依赖注入解决问题。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供/注入指的是在应用程序中提供数据、资源或依赖的方式。在软件开发中,应用程序通常依赖于外部模块或库。这些外部模块提供了许多重要的功能,比如数据库访问、文件操作、安全认证等。应用程序需要使用这些功能来完成其任务。然而,应用程序不能直接访问这些外部模块,必须通过提供或注入这些外部模块才能使用。 在提供模式中,应用程序自己提供所需的外部模块。这个模块可以是一个类、一个对象、一个服务或者一个库。由应用程序自己来管理这些模块的生命周期,可以创建多个实例,也可以共享一个实例。应用程序可以通过接口或者依赖注入的方式来访问这些模块。 在注入模式中,外部模块被注入到应用程序中。注入可以在应用程序启动时完成,也可以在应用程序运行时完成。在注入模式中,外部模块的生命周期由应用程序的容器来管理。容器会跟踪每个外部模块的状态,确保它们在需要的时候可用,并为每个需要它们的对象提供一个正确的实例。 这两种模式各有优缺点。提供模式更加自由灵活,可以更好地满足应用程序的个性化需求。注入模式更加封装,更容易管理和维护,也有利于代码的测试和调试。无论是提供还是注入,它们都有助于提高应用程序的质量和可维护性,促进团队合作和代码重用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值