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 ()来触发事件,父组件 ...
随机推荐
- OpenStack的架构详解(转)
OpenStack既是一个社区,也是一个项目和一个开源软件,它提供了一个部署云的操作平台或工具集.其宗旨在于,帮助组织运行为虚拟计算或存储服务的云,为公有云.私有云,也为大云.小云提供可扩展的.灵活的 ...
- C盘满了如何清理
一.C:\inetpub\logs\LogFiles\ 中的日志文件可以全部删除二.C盘上右键>属性>磁盘清理 和 系统磁盘清理三.百度下载:魔方清理大师>逐项清理四.卸载较大的不常 ...
- uploadify在chrome下初始化失败,在Firefox下却可以原因探析
如果没有报错,在其他浏览器下没问题,那就只有一种可能:浏览器flash加载失败,解决办法是,更改浏览器对站点flash的设置.参考下图:
- FSCapture截图软件注册码
企业版序列号: name:bluman serial/序列号/注册码:VPISCJULXUFGDDXYAUYF
- JVM 系列(一)类加载
JVM 系列(一)类加载 类加载机制是指把 class 文件加载到内存,并对数据进行校验.解析和初始化,最终形成 JVM 可以直接使用的 Java 类型的过程. ClassLoader 加载一个 cl ...
- win10如何安装和创建 证书
.下载winsdksetup.exe .在 MMC 管理单元中查看证书 打开一个命令提示符窗口. 类型mmc然后按 ENTER 键. 请注意,若要查看本地计算机存储中的证书,您必须具有管理员角色. 上 ...
- <摘录>开源软件架构-ZeroMQ
原文链接:http://www.aosabook.org/en/zeromq.html ØMQ是一个消息通信系统,如果你愿意的话也可以称其为“面向消息的中间件”.ØMQ的应用环境很广泛,包括金融服务. ...
- numpy 命令 ravel 等
xx.ravel() :表示把一个矩阵行优先展成一个向量.跟flatten一样. import numpy as np print (np.c_[np.array([[1,2,3],[2,3,5]] ...
- ListView单行刷新
之前要改变某一行ListView内容或者显示出删除按钮等,都要adapter.notifyDataSetChanged();刷新一下,数据少还可以,数据多的时候明显会消耗性能,单独刷新某一行就不会了, ...
- 用node.js写个在Bash上对字符串进行Base64或URL的encode和decode脚本
一:自己这段时间经常要用到Base64编码和URL编码,写个编译型语言有点麻烦干脆就用node.js弄了个,弄好后在/etc/profile里加上alias就能完成工具的配置,先上代码: functi ...