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 相关文章推荐
用js来获取上传的文件名纯粹是为了美化而用
Oct 23 Javascript
javascript学习笔记--数字格式类型
May 22 Javascript
推荐JavaScript实现继承的最佳方式
Nov 11 Javascript
jQuery+css实现的时钟效果(兼容各浏览器)
Jan 27 Javascript
浅谈JS中逗号运算符的用法
Jun 12 Javascript
JavaScript的==运算详解
Jul 20 Javascript
JS Input里添加小图标的两种方法
Nov 11 Javascript
对angularjs框架下controller间的传值方法详解
Oct 08 Javascript
JavaScript基于数组实现的栈与队列操作示例
Dec 22 Javascript
vue中axios实现数据交互与跨域问题
May 12 Javascript
VUEX-action可以修改state吗
Nov 19 Javascript
Vue js with语句原理及用法解析
Sep 03 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
linux下使用ThinkPHP需要注意大小写导致的问题
2011/08/02 PHP
php获取服务器端mac和客户端mac的地址支持WIN/LINUX
2014/05/15 PHP
crontab无法执行php的解决方法
2016/01/25 PHP
php实现微信公众号创建自定义菜单功能的实例代码
2019/06/11 PHP
Laravel 登录后清空COOKIE的操作方法
2019/10/14 PHP
javascript 放大镜效果js组件 qsoft.PopBigImage.v0.35 加入了chrome支持
2009/04/07 Javascript
JavaScript之Getters和Setters 平台支持等详细介绍
2012/12/07 Javascript
纯文字版返回顶端的js代码
2013/08/01 Javascript
js读取配置文件自写
2014/02/11 Javascript
Linux下编译安装php libevent扩展实例
2015/02/14 Javascript
JQuery中clone方法复制节点
2015/05/18 Javascript
理解Angular数据双向绑定
2016/01/10 Javascript
三种AngularJS中获取数据源的方式
2016/02/02 Javascript
简单了解Backbone.js的Model模型以及View视图的源码
2016/02/14 Javascript
基于layer.js实现收货地址弹框选择然后返回相应的地址信息
2017/05/26 Javascript
Jquery中attr与prop的区别详解
2017/05/27 jQuery
ionic 自定义弹框效果
2017/06/27 Javascript
vue 组件中添加样式不生效的解决方法
2018/07/06 Javascript
微信小程序项目实践之九宫格实现及item跳转功能
2018/07/19 Javascript
在vue项目中引用Iview的方法
2018/09/14 Javascript
详解vue更改头像功能实现
2019/04/28 Javascript
python执行get提交的方法
2015/04/29 Python
python的random模块及加权随机算法的python实现方法
2017/01/04 Python
Python内置模块ConfigParser实现配置读写功能的方法
2018/02/12 Python
对python修改xml文件的节点值方法详解
2018/12/24 Python
基于Python对数据shape的常见操作详解
2018/12/25 Python
python3+PyQt5 实现Rich文本的行编辑方法
2019/06/17 Python
Django跨域资源共享问题(推荐)
2020/03/09 Python
Python实现汇率转换操作
2020/05/03 Python
Python paramiko使用方法代码汇总
2020/11/20 Python
CSS3之2D与3D变换的实现方法
2019/01/28 HTML / CSS
销售经理岗位职责
2014/03/16 职场文书
村庄绿化方案
2014/05/07 职场文书
实名检举信范文
2015/03/02 职场文书
让世界充满爱观后感
2015/06/10 职场文书
分析ZooKeeper分布式锁的实现
2021/06/30 Java/Android