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 ...
随机推荐
- 机器学习: 基于MRF和CNN的图像合成
前面我们介绍了基于卷积神经网络的图像风格迁移,利用一张content image 和 style image,可以让最终的图像既保留content image的基本结构,又能显示一定的style im ...
- Linux性能测试 ulimit命令
功能说明:控制shell程序的资源. 语 法:ulimit [-aHS][-c <core文件上限>][-d <数据节区大小>][-f <文件大 小>][-m &l ...
- 几种常见RuntimeException
一般面试java Exception(runtimeException )是个问题必须要问 常见的异常上市45种,它的基本要求.许多其他....需要注意的积累 常见的几种例如以下: NullP ...
- Android 位置服务——BaiduLocation的使用
原文:Android 位置服务--BaiduLocation的使用 版权声明:本文为博主原创文章,欢迎转载,转载请在文章显眼处说明文章出处并给出连接. https://blog.csdn.net/To ...
- Parse陨落,开发者服务今后路在何方?
Parse为开发者提供移动应用的后台服务,包括数据存储.消息推送及用户管理等等.因此方便开发者可专心在客户端的制作,简化服务器端的设计. 关于 Parse 关停 2016年1月28日,Parse 官方 ...
- WPF实现选项卡效果(1)——使用AvalonDock
原文:WPF实现选项卡效果(1)--使用AvalonDock 简介 公司最近一个项目,软件采用WPF开发,需要实现类似于VS的选项卡(或者是浏览器的选项卡)效果.搜寻诸多资料后,发现很多同仁推荐Ava ...
- Wrapped的返回值取值
Bared Wrapped using Newtonsoft.Json; using Newtonsoft.Json.Linq; string str = JsonConvert.Serial ...
- WPF 用代码增加路由事件的方法
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threa ...
- js 动态操作元素
<!DOCTYPE html><html lang="en" xmlns="http://www.w3.org/1999/xhtml"> ...
- MVC 身份验证和异常处理过滤器
:在Global中注册为全局过滤器,应用于所有的Controller的Action 参数类均继承自ControllerContext,主要包含属性请求上下文.路由数据.结果 using FilterE ...