Vue组件通信—provide/inject

98 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

vue 开发中组件通信可谓是非常常见的操作的,而组件通信最常用的肯定是 props,但是props 使用于父子组件通信还比较方便,但是组件层级较多就时,props 操作起来就显得十分繁琐,也不便于书写;
注:为了方便,我就直接把 inject 放在子组件中

provide/inject 基本格式

  1. 父组件中 provide 格式

      <template>
        <div>
          {{a}}
          <test />
        </div>
      </template>
      <script>
      import test from './compoent/test.vue'
      export default {
        components: { test },
        name: 'showExcel',
          data () {
            return {
              // 定义一个对象,这里有一个小技巧,后面会讲到
              a: { b: 123 },
            }
          },
          provide () {
            return { a: this.a }
          },
      }
      </script>
    
  2. 子组件或孙子组件中 inject 基本格式

      <template>
        <div @click="changeA">{{a}}</div>
      </template>
    
      <script>
      export default {
        name: 'test',
        inject: ['a']
      }
      </script>
    
  3. 此时效果图:

1.webp

provide/inject inject 接收不到 provide 实时数据情况

  1. 真实开发中数据往往会从后端获取,此时直接在 provide 中声明该值后就会发现在孙子组件中是获取不到实时更新的值的,此时就需要借助方法来获取;

      // 父组件
      provide () {
        return { a: this.a, getA: this.getA }
      },
      mounted () {
        setTimeout(() => {
          this.a.b = '77';
        }, 2000);
      },
      methods: {
        getA () { return this.a }
      }
    
      // 子组件
      inject: ['a', 'getA'],
      mounted () {
        this.$nextTick(() => {
          console.log(this.getA()); // {b:123,c:77}
        }, 2000);
      },
    
  2. 这里使用 setTimeout 来模拟网络请求,在改变父组件 cc 的值后,子组件中接收到的 cc 的依然是最初我们赋予的初始值 123456,并没有改变;但是 通过方法 getCC
    返回的值是我们请求到的最新值,并且在视图中也是同样的效果;

      // 父组件
      data () {
        return {
          // 定义一个对象,这里有一个小技巧,后面会讲到
          a: { b: 123 },
          cc: 123456,
        }
      },
      provide () {
        return { a: this.a, cc: this.cc, getCC: this.getCC }
      },
      mounted () {
        setTimeout(() => {
          this.cc = '456'
        }, 2000);
      },
      methods: {
        getCC () { return this.cc },
      }
    
      // 子组件
      inject: ['getCC', 'cc'],
      mounted () {
        setTimeout(() => {
          console.log('cc', this.cc); // cc 123456
          console.log('getCC', this.getCC()); // getCC 456
        }, 3000);
      },
    
  3. 我们再在 父组件的 getCC 方法中增加一个辅助参数看看打印效果

2.webp ``` // 父组件

  // 子组件
  <template>
    <div>
      子组件中 cc:{{cc}}== getCC:{{getCC('888')}}
    </div>
  </template>

  <script>
  export default {
    name: 'test',
    inject: [ 'getCC', 'cc'],
    mounted () {
      setTimeout(() => {
        console.log('cc', this.cc); // cc 123456
        console.log('getCC', this.getCC('000')); // getCC 456
      }, 3000);
    },
  </script>
```
  1. 我们再来看看控制台打印效果

3.webp

  1. 从控制台效果图可以看出,父组件和子组件视图模板中 getCC 方法各自执行了两次,因为初始渲染视图时执行一次,在更新 cc 时又各自执行了一次,所以视图中的数据会有变化;