vue中provide和inject 用法

1、provide/inject有什么用?

常用的父子组件通信方式都是父组件绑定要传递给子组件的数据,子组件通过props属性接收,一旦组件层级变多时,采用这种方式一级一级传递值非常麻烦,而且代码可读性不高,不便后期维护。

vue提供了provideinject帮助我们解决多层次嵌套嵌套通信问题。在provide中指定要传递给子孙组件的数据,子孙组件通过inject注入祖父组件传递过来的数据。

其实,provide 和 inject 主要为高阶插件/组件库提供用例。并不推荐直接用于应用程序代码中。比如elementUI组件库中:
el-form组件中将组件实例暴露给子孙组件
 
el-form-item组件中注入el-form组件实例,然后就可以使用el-form组件实例的方法、变量等等。
 
为什么不使用父子组件props传值呢?
因为父子组件props传值需要需要知道往哪一个子组件传值,而el-form组件中会注入的子组件是不确定的。provide只需要将传递的值抛出,不需要知道使用哪一个子组件,子组件通过inject注入获取数据,也不需要知道父组件是谁,因此再封装组件库的时候很便利。
 
不推荐直接使用在应用程序代码中是因为数据追踪比较困难,不知道是哪一个层级声明了这个或者不知道哪一层级或若干个层级使用了。

2、provide/inject使用方式

provide:是一个对象,或者是一个返回对象的函数。里面呢就包含要给子孙后代的东西,也就是属性和属性值。注意:子孙层的provide会掩盖祖父层provide中相同key的属性值

inject:一个字符串数组,或者是一个对象。属性值可以是一个对象,包含fromdefault默认值,from是在可用的注入内容中搜索用的 key (字符串或 Symbol),意思就是祖父多层provide提供了很多数据,from属性指定取哪一个key;default指定默认值。
一种最常见的用法是刷新vue组件

3、例子

<template>
  <div
    id="app"
  >
    <router-view
      v-if="isRouterAlive"
    />
  </div>
</template>

<script>
export default {
  name: 'App',
  components: {
    MergeTipDialog,
    BreakNetTip
  },
  data () {
    return {
      isShow: false,
      isRouterAlive: true
  },

// 父组件中返回要传给下级的数据
  provide () {
    return {
      reload: this.reload
    }
  },
  methods: {
    reload () {
      this.isRouterAlive = false
      this.$nextTick(() => {
        this.isRouterAlive = true
      })
    }
  }
}
</script>
<template>
  <popup-assign
    :id="id"
    @success="successHandle"
  >
    <div class="confirm-d-tit"><span class="gray-small-btn">{{ name }}</span></div>
    <strong>将被分配给</strong>
    <a
      slot="reference"
      class="unite-btn"
    >
      指派
    </a>
  </popup-assign>
</template>
<script>
import PopupAssign from '../PopupAssign'
export default {
//引用vue reload方法
  inject: ['reload'],
  components: {
    PopupAssign
  },
methods: {
    // ...mapActions(['freshList']),
    async successHandle () {
      this.reload()
    }
  }
}
</script>

这样就实现了子组件调取reload方法就实现了刷新vue组件的功能,个人认为它实现了组件跨越组件传递数据方法。
下面一个例子祖组件的数据,祖孙元素调取
Ancestor.vue

 

<template>
    <div id="app">
    </div>
</template>
    <script>
        export default {
            data () {
                    return {
                        datas: [
                            {
                                id: 1,
                                label: '产品一'
                            },
                            {
                                id: 1,
                                label: '产品二'
                            },
                            {
                                id: 1,
                                label: '产品三'
                            }
                        ]
                    }
            },
            provide {
                return {
                    datas: this.datas
                }
            }
        }
    </script>

后代组件

 

<template>
    <div>
        <ul>
        <li v-for="(item, index) in datas" :key="index">
            {{ item.label }}
        </li>
        </ul>
    </div>
</template>
    <script>
        export default {
            inject: ['datas']
        }
    </script>

后代元素引入被注入数据datas,并在组件内循环输出

实际上,你可以把依赖注入看作一部分“大范围有效的 prop”,除了:
祖先组件不需要知道哪些后代组件使用它提供的属性
后代组件不需要知道被注入的属性来自哪里

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


 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值