provide-inject的作用

通常情况下,父组件向孙组件传递数据,可以采用父子props层层传递,也可以使用bus和Vuex直接交互。在Vue2.2.0之后,Vue还提供了provide/inject选项

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

也就是说,在父组件只要声明了provide,在其子组件,孙组件,曾孙组件等能形成上下游关系的组件中交互,无论多深都能通过inject来访问provider中的数据。而不是局限于只能从当前父组件的prop属性来获取。注意他只做祖先通后代的单向传递的一个办法。有人这么形容:

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

如何使用

使用方法
provide 提供变量:Object | () => Object
inject 注入变量: Array | { [key: string]: string | Symbol | Object }
provide 选项应该是一个对象或返回一个对象的函数。 该对象包含可注入其子孙的属性。在该对象中,它支持ES6中Symbol作为key,但只在原生支持等环境下可工作。

inject 选项可以是:
inject用来指定一个数组或者一个对象,数组的话就放provide里字段的名称,而对象的话可以指定
当前实例中的字段名
对应provide里的字段名
默认值或者返回默认值的函数

const Child = {
  inject: {
    foo: {
      from: 'msg',
      default: () => [1, 2, 3]
    }
  }
}

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

案例:

//App.vue中
<template>
<div v-cloak class="App">
  <box1 @myclick="fn"></box1>
</div>
</template>
<script>
  import box1 from "./components/box1.vue"
  export default {
    data() {
      return {
         msg:"父组件App传的值"
      }
    },
    methods: {
      fn(arr){
         this.msg=`父组件App传的值----${arr}`
      }
    },
   // provide选项提供变量
    provide:function(){
        return {msg:this.msg}
    },
    components: {
      box1,
    },
  }
</script>
//bo1文件中
<template>
 <box2></box2>
</template>
<script>
    import box2 from "./box2.vue"
    export default {
        inject:['msg'],
        components:{
            box2
        },
        provide:{data:"box2传递的值"}
    }
</script>
//bo2文件中
<template>
<div>
    <h3>{{msg}}--{{data}}</h3>
</div>
</template>
<script>
export default {
//在孙组件中,使用inject来注入
    inject:["msg",'data'],  
    methods: {
        fn(){
            this.$emit("myclick")
        }
    },
}
</script>

在这里插入图片描述

provide-inject如何实现响应式

方法一、父级组件为子级组件提供的数据为对象

//App.vue中
<template>
<div v-cloak class="App">
  <h1>父组件app中----{{msg.age}}</h1>
  <box1></box1>
</div>
</template>
<script>
  import box1 from "./components/box1.vue"
  export default {
    data() {
      return {
         msg:{name:"父组件App传的值",age:22}
      }
    },
    provide:function(){
        return {msg:this.msg}
    },
    components: {
      box1,
    },
  }
</script>
//bo1文件中
<template>
 <div>
    <button @click="fn">点击修改msg.age</button>
    <h2>子组件box1中----{{msg.age}}</h2>
    <box2></box2>
 </div>
</template>
<script>
    import box2 from "./box2.vue"
    export default {
        inject:['msg'],
        methods: {
            fn(){
                this.msg.age=100
            }
        },
        components:{
            box2
        },
    }
</script>
//bo2文件中
<template>
<div>
    <h2>子组件box2中----{{msg.age}}</h2>
</div>
</template>
<script>
export default {
    inject:["msg"], 
}
</script>

页面呈现:
在这里插入图片描述
当我们点击时:
在这里插入图片描述
可以看见所有组件都改变了

方法二、传递一个参数用方法返回

//App.vue中
<template>
  <div v-cloak class="App">
    <button @click="fn">点击修改msg</button>
    <h1>父组件app中----{{msg}}</h1>
    <box1></box1>
  </div>
</template>
<script>
  import box1 from "./components/box1.vue"
  export default {
    data() {
      return {
        msg: "父组件App传的值"
      }
    },
    methods: {
      fn() {
        this.msg = '父组件修改了数据'
      }
    },
    provide: function () {
      return { msg: () => this.msg }
    },
    components: {
      box1,
    },
  }
</script>
//box1文件中
<template>
    <div>
        <h2>子组件box1中----{{msg()}}</h2>
        <box2></box2>
    </div>
</template>
<script>
    import box2 from "./box2.vue"
    export default {
        inject: ['msg'],
        components: {
            box2
        },
    }
</script>
//bo2文件中
<template>
<div>
    <h2>子组件box2中----{{msg()}}</h2>
</div>
</template>
<script>
export default {
    inject:["msg"], 
}
</script>

页面呈现:
在这里插入图片描述
当我们点击修改时:
在这里插入图片描述

Logo

前往低代码交流专区

更多推荐