element-ui源码之组件通信那些事
最近在用element-ui重构前端项目,无意之中翻阅到一个比较好用的组件间通信方式,借助于vue的封装的发布-订阅消息模式与mixin语法。在开始之前先总结下vue常用的组件间通信方式,具体如下:
1、props与自定义事件
优点:常用的父子、子父组件传递方式,简单易懂
缺点:子父、父子之间传参比较高效,但是爷孙,兄弟组件之间存在通信短板,只能一级级传递
2、vue 2.4中新增的$attrs与$listeners
优点:解决了组件嵌套层次较深问题,通过在组件中绑定组件的属性值与监听组件的事件监听对象,子组件可以轻松访问到上层作用域的事件回调方法
缺点:相对于props与自定义事件,只是简化了写法,本质上属性也是一级级传递的,如果组件的层级是A>B>C,C组件如果想要访问到A组件的事件回调,那么在B组件中需要绑定A组件的属性attrs与事件对象listeners。
3、借助于发布-订阅模式
优点:发布-订阅设计模式所擅长点就是解决模块间通信,无论何种方式的通信方式,理论上都可以解决,在vue中,大量使用了该设计模式,只需要实例化一个vue实例,作为一个单独的事件中心引入即可。发布订阅模式具体内容可参考:https://www.cnblogs.com/gerry2019/p/10241488.html
缺点:发布-订阅模式只要有订阅消息,在分发事件的时候,都会触发订阅的回调,所以在开发过程中要注意自定义事件的命名空间,防止一些不必要的触发操作。
4、借助vuex管理状态
优点:引入状态管理,可以统一的管理项目状态,针对大型复杂项目适用性较好
缺点:需要额外维护一个vuex对象,中小型项目不适合
5、vue 2.2中新增的provide/inject
优点:可以从父组件注入需要共享给子元素的数据,如果注入的的数据是响应式,那么组件之间可以实现双向数据通信
缺点:官方并不推荐在业务代码中使用此模式,因为这种双向通信可能会导致组件的状态发生混乱
以上为vue中常用的几种组件间通信方式,以下为element-ui中采用的组件通信方式,本质上也是发布-订阅模式,与上述方法3大致相似,只是引入了自定义事件的生效的作用域,可以规避一些意料之外的事件触发。因为稍微不注意消息的命名空间,就可能会导致一些意外之外的错误,除此之外,当两个模块功能相似,如果单独都写一遍,可能存在大量冗余代码,在vue中我们想到的策略可能是借助于mixin,抽离公共的业务代码,但是假如抽离出了公共的消息订阅内容,那么此时问题就来了,如果我只想A模块内容发生改变,B模块不变,这个就会存在策略性问题,element-ui中的通信策略可以很好的规避掉以上两种坑,具体实现逻辑如下:
/**
*
* @param {目标组件名称} componentName
* @param {事件名称} eventName
* @param {载荷参数} params
*/
function broadcast(componentName, eventName, params) {
//递归子组件,查找命名空间内组件
this.$children.forEach(child => {
var name = child.$options.componentName; if (name === componentName) {
//分发子组件内订阅消息
child.$emit.apply(child, [eventName].concat(params));
} else {
broadcast.apply(child, [componentName, eventName].concat([params]));
}
});
}
export default {
methods: {
/**
*
* @param {目标组件名称} componentName
* @param {事件名称} eventName
* @param {载荷参数} params
*/
dispatch(componentName, eventName, params) {
var parent = this.$parent || this.$root;
var name = parent.$options.componentName;
//循环查询父组件,找到目标父组件
while (parent && (!name || name !== componentName)) {
parent = parent.$parent; if (parent) {
name = parent.$options.componentName;
}
}
if (parent) {
//分发父组件订阅内容
parent.$emit.apply(parent, [eventName].concat(params));
}
},
broadcast(componentName, eventName, params) {
broadcast.call(this, componentName, eventName, params);
}
}
};
从以上代码可以看出,在组件通信过程中,需要额外加一个componetName属性,其主要作用就是对分发的事件加入一个命名空间,命名空间内部的事件才会触发,否则会直接跳过,增加了业务代码的容错能力。在使用的过程中,只需要在需要引用的地方引入这个混入,就可以实现组件间双向通信。element-ui中的具体使用如下:


mixin语法可参考:https://cn.vuejs.org/v2/guide/mixins.html
mixin本质上就类似于继承,有助于简化业务代码
vue 2.x中部分新增组件通信方式可参阅vue API文档:https://cn.vuejs.org/v2/api/#provide-inject
element-ui源码之组件通信那些事的更多相关文章
- element ui源码解析 -- input篇
el-input是element ui中使用最频繁的组件之一了,分析其构成从四个方面入手:DOM结构,属性,样式,事件入手 DOM结构: <div> <input /> < ...
- element ui源码解析 -- button篇
要看源码就得从最简单的开始,button够简单的了,就从他开始吧. 安装依赖后源码目录在:node_modules/element-ui/packages中,可以看到这里的文件夹命名是不是很熟悉,就是 ...
- Element UI 源码—— Carousel 走马灯学习
参考博客:https://segmentfault.com/a/1190000014384638?utm_source=tag-newest
- iview 和 Elemet UI 源码比较
(近期给自己立了个小flag,读源码,每周至少读1篇源码) 下面来谈谈iview 和 Elemet UI 这两个基于Vue 的UI 框架源码的基本结构以及区别. 一.文件结构开发主要放在根文件夹下的s ...
- 项目源码--Android天气日历精致UI源码
下载源码 技术要点: 1. 天气日历精致UI 2. Android的Http通信技术 3. Android的天气信息解析 4. Android的日历信息的统计 5. Andorid的地理位置的管理 6 ...
- 修改elementUI源码新增组件/修改组件
前言 经常我们会遇到elementUI组件库期间有5%达不到我们想要的需求,第一我们重新写组件,第二我们改源码 安装element https://github.com/ElemeFE/element ...
- React源码之组件的实现与首次渲染
react: v15.0.0 本文讲 组件如何编译 以及 ReactDOM.render 的渲染过程. babel 的编译 babel 将 React JSX 编译成 JavaScript. 在 ba ...
- 04.ElementUI源码学习:组件封装、说明文档的编写发布
0x00.前言 书接上文.项目经过一系列的配置,开发脚手架已经搭建完毕.接下来开始封装自定义组件.并基于 markdown 文件生成文档和演示案例. 后续文章代码会根据篇幅,不影响理解的情况下进行部分 ...
- 【腾讯Bugly干货分享】深入源码探索 ReactNative 通信机制
Bugly 技术干货系列内容主要涉及移动开发方向,是由 Bugly 邀请腾讯内部各位技术大咖,通过日常工作经验的总结以及感悟撰写而成,内容均属原创,转载请标明出处. 本文从源码角度剖析 RNA 中 J ...
随机推荐
- 查看系统中安装了那些dotnet core 的SDK和运行时的命令
原文:查看系统中安装了那些dotnet core 的SDK和运行时的命令 1.查看SDK dotnet --list-sdks 2.查看运行时 dotnet --list-runtimes 效果如下图 ...
- 将普通java工程转换成maven工程
在MyEclipse10中将Maven项目转成普通Java项目后,想将Java项目转成Maven项目,结果一下子傻眼了.根本就没有攻略中提到的config标签.仔细一看,喵咪的,人家用的是Eclips ...
- CUDA一维纹理内存
纹理一词来源于GPU图形世界,GPU通用并行计算"盗用"了纹理一词,定义了一个纹理内存的概念.纹理内存缓存在 设备上,在某些情况下能减少对内存的请求并降低内存带宽的使用,是专门为那 ...
- Leetcode 122 Best Time to Buy and Sell Stock II 贪心
用一个数组表示股票每天的价格,数组的第i个数表示股票在第i天的价格.交易次数不限,但一次只能交易一支股票,也就是说手上最多只能持有一支股票,求最大收益. 关键:能赚就赚 class Solution ...
- 使用WPF实现3D场景[一]
原文:使用WPF实现3D场景[一] 在这篇文章里,将介绍如何实现一个简单的三维场景,一个三维的空间,包括空间内的三维物体的组合. 首先介绍一下一个三维场景里的基本元素: 先是定义一个简单的三维的场景环 ...
- 机器学习:深入理解LSTM网络 (二)
之前我们介绍了RNN 网络结构以及其所遇到的问题,RNN 结构对于关联度太长的时序问题可能无法处理, 简单来说,RNN对于太久远的信息不能有效地储存,为了解决这个问题,有人提出了LSTM的网络结构,L ...
- ASP.NET Core Razor 标签助手 - ASP.NET Core 基础教程 - 简单教程,简单编程
原文:ASP.NET Core Razor 标签助手 - ASP.NET Core 基础教程 - 简单教程,简单编程 ASP.NET Core Razor 标签助手 上一章节我们介绍了视图导入,学习了 ...
- 从源码角度看MySQL memcached plugin——1. 系统结构和引擎初始化
本章尝试回答两个问题: 一.memcached plugin与MySQL的关系: 二.MySQL系统如何启动memcached plugin. 1. memcached plugin与MySQL的关系 ...
- 微信小程序支付结果 c#后台回调
又为大家带来简单的c#后台支付结果回调方法,首先还是要去微信官网下载模板(WxPayAPI),将模板(WxPayAPI)添加到服务器上,然后在打开WxPayAPI项目中的example文件下的 Nat ...
- QT下的几种透明效果(QPalette背景白色,窗口设置setWindowOpacity,QPainter使用Clear模式绘图)
1.窗口整体透明,但是窗体上的控件不透明. 通过设置窗体的背景色来实现,将背景色设置为全透. QPalette pal = palette(); pal.setColor(QPalette::B ...