Vue-依赖注入(provide-inject)【祖孙传值】

前言-关于Vue组件的通讯方式

父子组件:

父向子传递数据是通过 props,子向父是通过 events($emit);
通过父链 / 子链也可以通信($parent / $children);
ref 也可以访问组件实例;
$root 获取根组件
provide / inject;
$attrs/$listeners;

兄弟通信:

EventBus
vuex
通过共同的父亲进行传递信息

跨级通信:

EventBus
vuex
provide / inject
$attrs/$listeners;
父子层层传递

1、什么是依赖注入

在我们日常开发的过程中,我们需要从父组件向子组件传递数据,会使用 props;如果组件层级过多,使用 props 沿着组件链逐级传递下去,十分的麻烦, provide 和 inject 就可以解决这一问题。

允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,父组件可以为其所有的后代组件提供依赖,并在起上下游关系成立的时间里始终生效,不论组件层次有多深。

注意:它只做祖先通后代的 单向传递 的一个办法。

provide 就相当于 加强版父组件prop,可以跨越中间组件;
inject 就相当于 加强版子组件的 props。

2、使用方法

provide:提供变量,在父组件中使用,是对象,对象里面可以返回变量 / 函数;
inject:注入变量,在后代组件中使用,可以是数组 / 对象。

① 基本用法—非响应式

在祖先组件中使用provide传值,在子组件中用inject接收。

// 祖先组件
data() {
    
    
  return {
    
    
     name: "卷儿"
  }
},
provide() {
    
    
  return {
    
    
     name: this.name
   }
 },
// 子组件
inject: ['name'],
    
<!-- 子组件中的使用方式 --> 
{
    
    {
    
     name }}

注意:这种方法传递过来的数据是没有响应性的,当你改变祖先组件中的name时,子组件中接收的name并不会改变。
官方解释:provide 和 inject 绑定并不是可响应的。这是刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的 property 还是可响应的。

② 常规用法—非响应式

方法一:传递的参数用一个方法返回

// 祖先组件
data() {
    
    
    return {
    
    
      name: "卷儿"
    }
  },
  provide() {
    
    
    return {
    
    
      newName: () => this.name
  }
// 子组件
inject: ['newName'],
computed: {
    
    
   hnewName() {
    
    
     return this.newName()
   }
 }
 

//子组件使用:
<!-- 子组件中的使用方式 -->
<h2>{
    
    {
    
     hnewName }}</h2> <!-- 推荐使用这种方法 -->
<h2>{
    
    {
    
     newName() }}</h2>

方法二:把需要传递的参数定义成一个对象

官方解释:provide 和 inject 绑定并不是可响应的。这是刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的 property 还是可响应的。

// 祖先组件
data() {
    
    
    return {
    
    
      obj: {
    
    
        name: "卷儿"
      }
    }
  },
  provide() {
    
    
    return {
    
    
    // 传递一个对象
      obj: this.obj
    }
  },
// 子组件
inject: ['obj'],
computed: {
    
    
    // 也可以不用计算属性重新定义
   objName() {
    
    
     return this.obj.name
   }
 }


<!-- 子组件中的使用方法 -->
<h2>obj的name: {
    
    {
    
    objName}}</h2>
<h2>obj的name: {
    
    {
    
    obj.name}}</h2>
 

③ 不太常规写法(响应式)

祖先组件使用provide传递整个this

// 祖先组件
data() {
    
    
    return {
    
    
        name: "卷儿"
    }
},
provide() {
    
    
    return {
    
    
      app: this, // 传递整个this过去
    };
}
inject: ["app"],// 拿到祖先组件的this 
mounted() {
    
    
    console.log(this.app.name)  // this.app 下面都是响应式的,因为都是同一实例下的引用
},

3、总结

  • provide/inject 是解决深层次的组件之间的通信问题,不受层级结构的限制。
  • 不能随便去滥用,通信代表着耦合;

优点
祖先组件不需要知道哪些后代组件使用它提供的数据;
后代组件不需要知道被注入的数据来自哪里;
不受层级结构的限制。
缺点
组件间的耦合较为紧密,不易重构;

猜你喜欢

转载自blog.csdn.net/qq_37831545/article/details/129030309