Vue2-provide与inject

70 阅读3分钟

1# provide

  • 语法: provide: Object | () => Object
  • 作用: provide 选项用于在组件中提供数据,以便子组件可以通过 inject 选项来注入这些数据。
  • 参数
    • 可以是一个对象,其中包含要共享的数据或方法。
    • 也可以是一个返回对象的函数,用于动态地提供数据。

2# inject

  • 语法: inject: Array<string> | { [key: string]: string | Symbol | Object }
  • 作用: inject 选项用于声明要从父组件注入的数据属性。
  • 参数
    • 可以是一个字符串数组,每个字符串表示要注入的属性名。
    • 也可以是一个对象,其中键是本地绑定的名称,值是从父级注入的属性的名称、Symbol 或对象。

注意:provide 和 inject 绑定并不是可响应的,这是刻意为之的。然而,如果你传入一个可监听的对象,那么其对象的属性是可响应的。

示例一:提供非响应式数据

父组件可以传递 stringbooleannumberarrayobject 类型的数据给子组件,这些数据可以直接在子组件模板中使用,同时也可以通过计算属性对这些数据进行处理后再展示。

  1. 父组件:Parent.vue
<template>
  <Child></Child>
</template>

<script>
import Child from './Child.vue';
export default {
  components: { Child },
  provide() {
    return {
      stringValue: 'Hello Vue', // 提供字符串类型数据
      booleanValue: true, // 提供布尔类型数据
      numberValue: 42, // 提供数字类型数据
      arrayValue: [1, 2, 3], // 提供数组类型数据
      objectValue: {
        name: 'lee',
        age: 25
      } // 提供对象类型数据
    };
  }
}
</script>
  1. 子组件:Child.vue
<template>
  <div>
    <!-- 直接在模板中使用 -->
    <p>Injected Data:</p>
    <ul>
      <li>String Value: {{ stringValue }}</li>
      <li>Boolean Value: {{ booleanValue }}</li>
      <li>Number Value: {{ numberValue }}</li>
      <li>Array Value: {{ arrayValue }}</li>
      <li>Object Value: {{ objectValue }}</li>
    </ul>
    
    <!-- 通过计算属性使用 -->
    <p>Computed Property:</p>
    <p>{{ computedData }}</p>
  </div>
</template>

<script>
export default {
  inject: ['stringValue', 'booleanValue', 'numberValue', 'arrayValue', 'objectValue'],
  computed: {
    computedData() {
      return this.stringValue;
    }
  }
};
</script>

示例二:提供响应式数据

父组件传递响应式数据的方式有:(1)传入一个响应式对象;(2)通过匿名函数提供值;(3)直接传值;(4)直接提供组件实例。在这四种方式中,当父组件点击更新按钮时,只有方式(1)、方式(2)和方式(4)传递的值会发生响应式变化;而当子组件点击更新按钮时,只有方式(1)和方式(4)传递的值会发生响应式变化。

  1. 父组件:Parent.vue
<template>
  <div>
    <p>Parent Component</p>
    <p>Name: {{ objValue.name }}</p>
    <p>String Value: {{ stringValueFn() }}</p>
    <p>String Value: {{ computedStringValue }}</p>
    <p>Number Value: {{ numberValue }}</p>
    <button @click="change">Parent - Change Values</button>
    <!-- 父组件点击更新按钮后,方式1、方式2、方式4 传递的值会响应式变化 -->
    <hr/>
    <Child></Child>
  </div>
</template>

<script>
import Child from "./Child.vue";
export default {
  components: { Child },
  data() {
    return {
      objValue: {
        name: "Vue",
      },
      stringValue: "Hello Vue!",
      numberValue: 11,
      value: 'Vue',
    };
  },
  computed() {
    computedStringValue(){
      return this.stringValueFn();
    }
  },
  provide() {
    return {
      // 方式1. 传入一个响应式对象
      objValue: this.objValue,

      // 方式2. 通过匿名函数来提供值
      stringValueFn: () => this.stringValue,
        
      // 方式3. 直接传值
      numberValue: this.numberValue,
        
      // 方式4. 直接提供组件实例
      parent: this,
    };
  },
  methods: {
    change() {
      this.objValue.name = "Parent"; // 方式1
      this.stringValue = "Hello Parent!"; //方式2
      this.numberValue = 22; // 方式3
      this.parent.value = 'Parent'; // 方式4
    },
  },
};
</script>
  1. 子组件:Child.vue
<template>
  <div>
    <p>Child Component</p>
    <p>Name: {{ objValue.name }}</p>
    <p>String Value: {{ stringValueFn() }}</p>
    <p>Number Value: {{ numberValue }}</p>
    <p>Parent Value: {{ parent.value }}</p>
    <button @click="change">Child - Change Values</button>
    <!-- 子组件点击更新按钮后,方式1、方式4 传递的值会响应式变化 -->
  </div>
</template>

<script>
export default {
  inject: ['objValue', 'stringValueFn', 'numberValue', 'parent'],
  methods: {
    change() {
      this.objValue.name = 'Child'; // 方式1
      this.parent.value = 'Child'; // 方式4
    },
  },
}
</script>