Regular进阶: 跨组件通信
本文由作者郑海波授权网易云社区发布。
背景
在组件化不断深入的大环境下,无论使用哪种 MDV 框架都最终会遇到一个头疼的问题,就是「跨组件通信」。
下图是个简单的例子

这里包含「事件通信」和「数据通信」两个维度。
事件传递
为了将事件 click 从 <LeafNode /> 传递到最外层组件,需要依次通过 <SubNode /> 和 <Sub /> 等可能本不关心这个事件的组件(即使例子里已经使用了proxy的简化语法)
数据传递
为了从 <Top /> 传递 title 这个 prop 到 <LeafNode /> , 需要层层跨越 <Sub />、<SubNode /> 这些本不需要关心 title属性 的组件。
以上处理方式除了带来性能上的损耗之外,更麻烦的就是造成了可维护性的急速下降。
显而易见的事件通信解决方案
最直接的做法就是引入一个「中介者」,简而言之就是一个全局的「跳板」,下例就是一个事件中介者
mediator.js
const Regular = require('regularjs');const emitter = new Regular;//每个Regular组件都是一个事件发射器module.exports = {
broadcast: emiter.$emit.bind(emiter),
subscribe: emiter.$on.bind(emiter)
}
Top.js
const { broadcast, subscribe } = require('./mediator')const Regular = require('regularjs');const Top = Regular.extend({
name: 'Top',
init(){
subscribe('check', ev =>{ // 通过emitter广播事件
})
}
})
LeafNode.js
const { broadcast, subscribe } = require('path/to/mediator')const Regular = require('regularjs');const LeafNode = Regular.extend({
template: `<div on-click={ this.onClick() } ></div>`,
name: 'LeafNode',
onClick(){
broadcast( 'check', { type: 'leafnode' } )
}
})
mediator 作为一个全局单例直接被 LeafNode 和 Top 引用,通过它实现了直接通信.
更麻烦的兄弟节点之间的通信当然也可以这样来解决。
显而易见的解决方案引出的另一个显而易见的问题
上述中介者的引入的最大问题就是,所有相关组件都在 定义时 引入了对emitter的 全局耦合, 这个将导致组件无法在多工程间被复用。
一种合理的解决方案就是将对emitter的耦合, 延迟到实例化阶段。
在Regular之前的版本里,很多朋友会通过this.$parent或this.$outer等可控性很差的方式来实现,在v0.6有了一种更好的方式。
modifyBodyComponent 新生命周期
在 Regular 的 v0.6 引入了一个新的生命周期叫 modifyBodyComponent ,它用来劫持到组件包裹的所有内部组件的初始化周期。
我们用一个简单例子来实现下emitter的动态注入
Broadcastor.js
const Regular = require('regularjs');const Broadcastor = Regular.extend({
name: 'Broadcastor',
config( data ){ const emitter = data.emitter; this._broadcast = emitter.$emit.bind(emitter), this._subscribe = emitter.$on.bind(emitter)
},
modifyBodyComponent( component, next ){
component.$broadcast = this._broadcast;
component.$subscribe = this._subscribe;
next(component) // 交给外层的包装器
}
})
Top.js
// const { broadcast, subscribe } = require('./mediator')const Regular = require('regularjs');const Top = Regular.extend({
name: 'Top',
template: '略...',
init(){ this.$subscribe('check', ev =>{ // 通过emitter广播事件
})
}
})
LeafNode.js
// const { broadcast, subscribe } = require('path/to/mediator')const Regular = require('regularjs');const LeafNode = Regular.extend({
template: `<div on-click={ this.onClick() } ></div>`,
name: 'LeafNode',
onClick(){
this.$broadcast( 'check', { type: 'leafnode' } )
}
})
main.js (入口)
new Regular({
template:`
<Broadcastor emitter={emitter}> <!-- 其中LeafNode 在Top内部 -->
<Top />
</Broadcastor>
`,
data: {
emitter: new Regular
}
})
这样所有的组件声明都取消了对全局 emitter 的直接依赖,而是在入口(main.js) 动态传入了一个emitter。
生命周期
需要注意的是modifyBodyComponent 会在 component本身compile之后运行, 但在init之前运行。以上面的例子为代表, 完整生命周期如下.
Broadcastor.config -> Broadcastor.compile
- Top.config -> Top.compile
- LeafNode.config -> LeafNode.compile
- Broadcastor.modifyBodyComponent(LeafNode)
- LeafNode.init
- Broadcastor.modifyBodyComponent(Top)
- Top.init
- Broadcastor.init
下一篇,应该会以redux(rgl-redux)为例,介绍一种基于modifyBodyComponent来解决跨组件的数据通信的方式
免费领取验证码、内容安全、短信发送、直播点播体验包及云服务器等套餐
更多网易技术、产品、运营经验分享请访问网易云社区。
相关文章:
【推荐】 测试周期内测试进度报告规范
【推荐】 如何实现360度的手游安全防护?网易云易盾专家分享最新实践
Regular进阶: 跨组件通信的更多相关文章
- redux搭配react-redux进行跨组件通信开发
Redux API 作用 createStore 用于创建一个store对象 bindActionCreators 用于简化操作,不用开发者手动触发dispatch React-redux API 作 ...
- vue跨组件通信的几种方法
http://www.tuicool.com/articles/jyM32mA 在开发组件的时候,一定会遇到组件的通信,比如点击一个图标出现弹窗和蒙层,这三个分别是不同的组件.管理他们之间的状态就成了 ...
- Regular进阶: 几点性能优化的建议
本文由作者郑海波授权网易云社区发布. 本文旨在用 20% 的精力解决使用Regular过程中 80% 的性能问题. 这里大部分是关于脏检查的性能优化,不了解的可以先看下<Regular脏检查介绍 ...
- vue组件之间的传值——中央事件总线与跨组件之间的通信($attrs、$listeners)
vue组件之间的通信有很多种方式,最常用到的就是父子组件之间的传值,但是当项目工程比较大的时候,就会出现兄弟组件之间的传值,跨级组件之间的传值.不可否认,这些都可以类似父子组件一级一级的转换传递,但是 ...
- Vue组件跨层级通信
正常组件间通信 父->子组件 是通过属性传递 子->父组件 是通过this.$emit()传递 this.$emit()返回的是this,如果需要一些值 可使用callback方式传递 p ...
- vue任意关系组件通信与跨组件监听状态 vue-communication
大家好!我是木瓜太香! 众所周知,组件式开发方式给我们带来了方便,不过也引入了新的问题,组件之间的数据就像被一道无形的墙隔开,如果我们希望临时让两个组件直接通信,vuex 太巨,而 $emit 又不好 ...
- react第六单元(react组件通信-父子组件通信-子父组件通信-跨级组件的传参方式-context方式的传参)
第六单元(react组件通信-父子组件通信-子父组件通信-跨级组件的传参方式-context方式的传参) #课程目标 1.梳理react组件之间的关系 2.掌握父子传值的方法 3.掌握子父传值的方法 ...
- Android随笔之——跨进程通信(一) Activity篇
在Android应用开发中,我们会碰到跨进程通信的情况,例如:你用QQ通讯录打电话的时候会调用系统的拨号应用.某些新闻客户端可以将新闻分享到QQ.微信等应用,这些都是跨进程通信的情况.简而言之,就是一 ...
- vue组件详解(三)——组件通信
组件之间通信可以用下图表示: 组件关系可分为父子组件通信.兄弟组件通信.跨级组件通信. 一.自定义事件 当子组件需要向父组件传递数据时,就要用到自定义事件. 子组件用$emit ()来触发事件,父组件 ...
随机推荐
- Extjs Vbox布局方式,以及align种类,flex,pack属性含义简介
VBox布局方式,熟悉下一下几个主要属性: 一.align:字符类型,指示组件在容器内的对齐方式.这个是基于容器的左上角来排列的.pack不同,pack是根据容器的最上边来显示的. 1.left(默认 ...
- nginx反向代理部署与演示(二)
我们把LB01作为负载均衡器,WEB01和WEB02作为两台web服务器. WEB01与WEB02虚拟主机配置如下: 我们修改nginx下的conf/nginx.conf文件,在http{}中 ...
- geoserver 问题解决
GeoServer的8080端口被占用了怎么办?如何修改GeoServer的端口? GeoServer管理页面的登陆地址正常情况下为:http://localhost:8080/geoserver/w ...
- python如何查看有哪些模块
Question: 如何查看正则表达式模块re及其相关函数的意义 1.终端命令行下 python >> import sys >> sys.modules ########## ...
- Bioconductor简介
Bioconductor简介 2012-10-09 ~ ADMIN 源:Bioconductor: open software development for computational biolog ...
- 欲哭无泪的p-value = 0.051 | 做几次重复能得到较低的p-value
欲哭无泪的p-value = 0.051 | 做几次重复能得到较低的p-value 已有 1469 次阅读 2017-12-15 14:12 |个人分类:RNA-seq|系统分类:科普集锦|关键词:R ...
- Jmeter中的XPath Assertion
XPath 是一门在 XML 文档中查找信息的语言.XPath 可用来在 XML 文档中对元素和属性进行遍历. XPath 是 W3C XSLT 标准的主要元素,并且 XQuery 和 XPointe ...
- CSV 文件
CSV 文件 CSV(Comma Separated Values 逗号分隔值) 是一种文件格式(如.txt..doc等),也可理解 .csv 文件就是一种特殊格式的纯文本文件.即是一组字符序列,字符 ...
- Java 8 新日期时间 API
Java 8 新日期时间 API 1. LocalDate.LocalTime.LocalDateTime LocalDate.LocalTime.LocalDateTime 实例是不可变的对象,分别 ...
- Android系统root破解原理分析
http://dengzhangtao.iteye.com/blog/1543494 root破解过程的终极目标是替换掉系统中的su程序.但是要想替换掉系统中su程序本身就是需要root权限的,怎样在 ...