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 ()来触发事件,父组件 ...
随机推荐
- SpringMVC工作原理1(基础机制)
图1.基本原理图 Spring工作流程描述 1. 用户向服务器发送请求,请求被Spring 前端控制Servelt DispatcherServlet捕获: 2. Dispat ...
- ContentProvider-------------自定义的内容提供者 然后去访问
自定义提供者 import android.content.Context; import android.database.DatabaseErrorHandler; import android. ...
- WebMagic写的网络爬虫
一.前言 最近因为有爬一些招聘网站的招聘信息的需要,而我之前也只是知道有“网络爬虫”这个神奇的名词,具体是什么.用什么实现.什么原理.如何实现比较好都不清楚,因此最近大致研究了一下,当然,研究的并不是 ...
- nginx 反向代理 502 Bad Gateway
查看nginx的error.log日志文件发现如下信息: upstream sent too big header while reading response header from upstrea ...
- php在线支付流程
1.企业与银行的两种接入方式: (1).企业直接与银行对接. 优点:直接与银行进行财务结算,资金安全,适合资金流较大企业. 缺点:开发和维护工作量较大,分别与每家银行签订合同,每年需交 ...
- jxl 创建excel
public static void performanceExcel(String sCurrPath,List<Record> list, String begin,String en ...
- VC字符串处理整理
场景: 1.在存储数据时有时接口需要合并字符串值,并以某些特殊字符来合并部分,到需要的时候再分割它.如一些数值,人名等. 2.C++有strtok,stringstream和find函数来实现分割.可 ...
- MySQL主从复制备份
前言 数据库实时备份的需求很常见,MySQL本身提供了 Replication 机制,摘译官方介绍如下: MySQL Replication 可以将一个主数据库中的数据同步到一个或多个从数据库中.并且 ...
- 在windows系统下安装oracle 11g
oracle 11g 安装在windows server 2012 系统下. 最近,需要配置数据库,要求在windows操作系统下,安装oracle 11g 数据库,因为以前没有安装过,所以成功后, ...
- CComSafeArray
https://blog.csdn.net/tangaowen/article/details/6554640