Vue组件通信入门之Provide和Inject机制


Posted in Javascript onDecember 29, 2019

前言

Vue中父组件到子组件的通信主要由子组件的props属性实现。但是在一些情况下,父组件无法直接向子组件的props传值。比如子组件通过父组件的slot进入父组件,父组件根本不知道子组件是谁,更不用说用子组件的props了。这时应该怎么办呢?Vue在2.2.0版本引入了provide与inject,正好适合处理这一情况。

什么是provide与inject

用文档的话说:

provide/inject需要一起使用,以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在起上下游关系成立的时间里始终生效。如果你熟悉 React,这与 React 的上下文特性很相似。

这就是说从父组件的provide属性传入一个对象,子组件(或者是孙组件,只要是子级组件)可以用inject属性接收父组件的provide属性。比如

// main.vue
<template>
  <c1 message="hello world">
    <c2></c2>
  </c1>
</template>
 
// c1.vue
<template>
 <div id="c1">
  <slot></slot>
 </div>
</template>
 
<script>
export default {
 props: ['message'],
 provide () {
  return {
   message: this.message
  }
 }
}
</script>
 
// c2.vue
<template>
 <div id="c2">
   {{ message }}
 </div>
</template>
 
<script>
export default {
 inject: ['message']
}
</script>

上面的main组件会被渲染为:

<div id="c1">
 <div id= "c2">hello world</div>
</div>

可以看到,c1组件在不清楚子组件是什么的情况下,将它的props中的message传给了c2组件。在这里c1组件就像是一个数据源一样,为子组件提供数据。但是,c1组件提供的数据仅在c1的子孙组件中可见,因此可以算作是有作用域限定的数据源。

父到子孙组件方向的数据流

父到子孙组件方向是provide/inject机制设计时的数据流方向。我们可能会猜想,在父组件中更改provide的值,子组件会响应式的发生改变。但是注意到文档中话。

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

这意味着,如果provide的值不是可监听对象时,在父组件中更改provide的值,子组件不会发生任何变化。比如模板仍然为上面那个例子的模板,message的值是一个props属性,不是可监听对象,如果我们在c1的mounted钩子函数里改变message的值。如:

// c1.vue
<script>
export default {
 //...
 mounted () {
  setTimeout( () => {
   this.message = 'Opps, it would not be rendered'
  }, 1000)
 }
}
</script>

子组件不会响应修改后的值。

但是如果provide的值是一个可监听对象呢?请看一下例子:

<script>
// c1.vue
export default {
 data () {
  return {
   message: 'hello world'
  }
 },
 provide () {
  messageData: this.$data
 },
 mounted () {
  setTimeout(() => {
   this.message = 'I can show in c2.'
  }, 10000)
 }
}
</script>
 
// c2.vue
<template>
 <div id="c2">
  {{ messageData.message }}
 </div>
</template>
 
<script>
export default {
 inject: ['messageData']
}
</script>

此时在c1挂载10s后,子组件将会显示I can show in c2。为什么呢?c2中messageData实际上就是c1实例的this.$data。而this.$data上有message的响应式getter与setter。所以c2的视图会被message的dep收集,因此在c1中更新message,c2的视图也会更新。

纵观整个过程,provide/inject机制是非响应式的,即provide与inject之间没有绑定。具体的值是在子组件初始化过程中决定的。

总结

provide/inject提供了一种新的组件间通信的方法。它允许父组件向子孙组件间进行跨层级的数据分发。但是provide/inject是非响应式的,如果要子孙组件根据父组件的值进行改变,provide/inject机制不是一个好的选择。此时可以使用Vuex来管理状态。

好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对三水点靠木的支持。

Javascript 相关文章推荐
JavaScript Distilled 基础知识与函数
Apr 07 Javascript
javascript使用中为什么10..toString()正常而10.toString()出错呢
Jan 11 Javascript
js类型转换与引用类型详解(Boolean_Number_String)
Mar 07 Javascript
jQuery实现的给图片点赞+1动画效果(附在线演示及demo源码下载)
Dec 31 Javascript
详谈jQuery中使用attr(), prop(), val()获取value的异同
Apr 25 jQuery
关于Vue.nextTick()的正确使用方法浅析
Aug 25 Javascript
原生javascript实现的全屏滚动功能示例
Sep 19 Javascript
浅析JS抽象工厂模式
Dec 14 Javascript
原生js实现移动端Touch轮播图的方法步骤
Jan 03 Javascript
详解微信小程序之scroll-view的flex布局问题
Jan 16 Javascript
Layui 带多选框表格监听事件以及按钮自动点击写法实例
Sep 02 Javascript
vue中的.$mount('#app')手动挂载操作
Sep 02 Javascript
JS中数组实现代码(倒序遍历数组,数组连接字符串)
Dec 29 #Javascript
如何基于JavaScript判断图片是否加载完成
Dec 28 #Javascript
Vue页面刷新记住页面状态的实现
Dec 27 #Javascript
uni-app 组件里面获取元素宽高的实现
Dec 27 #Javascript
Vue中axios拦截器如何单独配置token
Dec 27 #Javascript
JavaScript获取当前url路径过程解析
Dec 27 #Javascript
前端开发之便利店收银系统代码
Dec 27 #Javascript
You might like
新手菜鸟必读:session与cookie的区别
2013/08/22 PHP
使用php转义输出HTML到JavaScript
2015/03/27 PHP
WordPress中&quot;无法将上传的文件移动至&quot;错误的解决方法
2015/07/01 PHP
解析 thinkphp 框架中的部分方法
2017/05/07 PHP
Javascript实例教程(19) 使用HoTMetal(2)
2006/12/23 Javascript
JQuery 写的个性导航菜单
2009/12/24 Javascript
JavaScript中Math对象方法使用概述
2014/01/02 Javascript
jquery实现html页面 div 假分页有原理有代码
2014/09/06 Javascript
JS实现日期时间动态显示的方法
2015/12/07 Javascript
浅析Bootstrap表格的使用
2016/06/23 Javascript
浅谈AngularJs指令之scope属性详解
2016/10/24 Javascript
微信小程序 缓存(本地缓存、异步缓存、同步缓存)详解
2017/01/17 Javascript
实例解析js中try、catch、finally的执行规则
2017/02/24 Javascript
javascript使用btoa和atob来进行Base64转码和解码
2017/03/20 Javascript
微信JSAPI Ticket接口签名详解
2020/06/28 Javascript
基于react后端渲染模板引擎noox发布使用
2018/01/11 Javascript
layui获取选中行数据的实例讲解
2018/08/19 Javascript
微信小程序自定义toast的实现代码
2018/11/16 Javascript
Node4-5静态资源服务器实战以及优化压缩文件实例内容
2019/08/29 Javascript
VSCode插件安装完成后的配置(常用配置)
2020/08/24 Javascript
[49:21]2018DOTA2亚洲邀请赛3月30日 小组赛B组 Effect VS iG
2018/03/31 DOTA
python实现的用于搜索文件并进行内容替换的类实例
2015/06/28 Python
Django中传递参数到URLconf的视图函数中的方法
2015/07/18 Python
Python数据分析之双色球中蓝红球分析统计示例
2018/02/03 Python
如何在Python中实现goto语句的方法
2019/05/18 Python
django 单表操作实例详解
2019/07/30 Python
python的slice notation的特殊用法详解
2019/12/27 Python
在django admin详情表单显示中添加自定义控件的实现
2020/03/11 Python
Python实现壁纸下载与轮换
2020/10/19 Python
GEOX鞋美国官方网站:意大利会呼吸的鞋
2017/07/12 全球购物
意大利网上药房:Farmacia 33
2020/01/27 全球购物
社会实践先进工作者事迹材料
2014/05/06 职场文书
三好学生个人总结
2015/02/15 职场文书
党员评议自我评价
2015/03/03 职场文书
劳保用品管理制度范本
2015/08/06 职场文书
使用pycharm运行flask应用程序的详细教程
2021/06/07 Python