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 ...
随机推荐
- Windows PowerShell 学习之——Cmdlet处理生命周期
这一次介绍一下Cmdlet处理过程的生命周期 总共分为六个部分 1.概述 2. 命令行输入绑定参数(parameters) 3. 开始指令处理 4. 接受管道输入绑定参数 5. 处理记录 6. 处理记 ...
- Android显示gif格式图片
大家知道,在Android中使用ImageView来显示gif格式的图片,我们无法得到gif格式图片该有的效果,它只会停在第一帧上,而不会继续.这时只能看到一张静态的图片,这里我们可以使用个简单的方法 ...
- JAVA学习第三十三课(经常使用对象API) —迭代器
数字有非常多用数组存,对象有非常多就要用集合存 可是数组是固定长度的,集合是可变长度的 集合的由来: 对象用来封装特有数据,对象多了须要存储,假设对象个数不确定,就须要使用集合容器来存储 集合的特点: ...
- WinRAR 5.50 简体中文正式版发布(20多项改进)
感谢ikimi的投递 流行好用的压缩工具,支持鼠标拖放及外壳扩展,完美支持 ZIP 档案,内置程序可以解开 CAB.ARJ.LZH.TAR.GZ.ACE.UUE.BZ2.JAR.ISO 等多种类型的压 ...
- 圆周卷积(circular convolution)
1. 定义与概念 圆周卷积也叫循环卷积, 2. 实现(matlab) 以圆周的形式卷积两个信号: >> z = ifft(fft(x).*fft(y));
- EntityFrameworkCore 单表树状结构配置
数据结构 public class TreeNode { [Key] public long Id { get; set; } public string NodeName { get; set; } ...
- 使用 NodeJS + Express从GET/POST Request 取值
过去无论哪一种网站应用程式的开发语言,初学者教学中第一次会提到的起手式,八九不离十就是GET/POST Request 的取值.但是,在Node.js + Express 的世界中,仿佛人人是高手,天 ...
- layerui
引用layer.js,官网:http://layer.layui.com/常用属性:btn/icon/skin/time/content/yes(点击确认.提交) 常用窗体.alert layer.a ...
- Bootstrap 标签徽章巨幕页头
@{ Layout = null;}<!DOCTYPE html><html><head> <meta name="viewport&q ...
- 在 win10 环境下,设置自己写的 程序 开机自动 启动的方法
原文:在 win10 环境下,设置自己写的 程序 开机自动 启动的方法 1.是登录自己用户时才能开机启 C:\Users\username\AppData\Roaming\Microsoft\Wind ...