最近在用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源码之组件通信那些事的更多相关文章

  1. element ui源码解析 -- input篇

    el-input是element ui中使用最频繁的组件之一了,分析其构成从四个方面入手:DOM结构,属性,样式,事件入手 DOM结构: <div> <input /> < ...

  2. element ui源码解析 -- button篇

    要看源码就得从最简单的开始,button够简单的了,就从他开始吧. 安装依赖后源码目录在:node_modules/element-ui/packages中,可以看到这里的文件夹命名是不是很熟悉,就是 ...

  3. Element UI 源码—— Carousel 走马灯学习

    参考博客:https://segmentfault.com/a/1190000014384638?utm_source=tag-newest

  4. iview 和 Elemet UI 源码比较

    (近期给自己立了个小flag,读源码,每周至少读1篇源码) 下面来谈谈iview 和 Elemet UI 这两个基于Vue 的UI 框架源码的基本结构以及区别. 一.文件结构开发主要放在根文件夹下的s ...

  5. 项目源码--Android天气日历精致UI源码

    下载源码 技术要点: 1. 天气日历精致UI 2. Android的Http通信技术 3. Android的天气信息解析 4. Android的日历信息的统计 5. Andorid的地理位置的管理 6 ...

  6. 修改elementUI源码新增组件/修改组件

    前言 经常我们会遇到elementUI组件库期间有5%达不到我们想要的需求,第一我们重新写组件,第二我们改源码 安装element https://github.com/ElemeFE/element ...

  7. React源码之组件的实现与首次渲染

    react: v15.0.0 本文讲 组件如何编译 以及 ReactDOM.render 的渲染过程. babel 的编译 babel 将 React JSX 编译成 JavaScript. 在 ba ...

  8. 04.ElementUI源码学习:组件封装、说明文档的编写发布

    0x00.前言 书接上文.项目经过一系列的配置,开发脚手架已经搭建完毕.接下来开始封装自定义组件.并基于 markdown 文件生成文档和演示案例. 后续文章代码会根据篇幅,不影响理解的情况下进行部分 ...

  9. 【腾讯Bugly干货分享】深入源码探索 ReactNative 通信机制

    Bugly 技术干货系列内容主要涉及移动开发方向,是由 Bugly 邀请腾讯内部各位技术大咖,通过日常工作经验的总结以及感悟撰写而成,内容均属原创,转载请标明出处. 本文从源码角度剖析 RNA 中 J ...

随机推荐

  1. 一组西门子S7 报文

    03 00 00 16 11 E0 00 00 00 01 00 C1 02 10 00 C2 02 03 01 C0 01 0A(第一次握手报文) 03 00 00 16 11 D0 00 01 0 ...

  2. Numpy Usage Introduction

    Reference : http://my.oschina.net/u/175377/blog/74406 试验性的Numpy教程 原文来自Tentative NumPy Tutorial 目录 先决 ...

  3. centos7 Intellij Idea 授权服务器搭建(Jetbrain 家族系列IDE)

    centos7 Intellij Idea 授权服务器搭建 1.上传破解文件 我用的是Xshell客户端,有上传功能,但是linux必须先装lrzsz,也可以通过其他方式传到linux上 yum -y ...

  4. Atitit.Gui控制and面板----db数据库领域----- .比较数据库同步工具 vOa

    Atitit.Gui控制and面板----db数据库区----- .数据库比較同步工具 vOa 1. 咨微海信数据库应用 工具 1 2. 数据库比較工具 StarInix SQL Compare    ...

  5. keras 的使用

    theano 以及 TensorFlow 是 keras 的 backend(后端支持),因此,keras 本质上是对 thenao 或者 TensorFlow 的进一步封装(wrapper). ke ...

  6. BSD介绍

    BSD许可证模板  * Copyright (c) 1998, Regents of the University of California  * All rights reserved.    * ...

  7. IME输入法编程心得

    原文:IME输入法编程心得 posted @ 2012-11-30 00:42 from [FreedomShe] 自然语言处理的输入法作业成品没有做出来,但不想再在蛋疼的Win32上面耗费时间了,整 ...

  8. rocksdb源码——性能诊断

    该文前三部份介绍 statistics.perf context和iostat context和thread status相关内容.最后介绍ThreadLocalPtr实现的原理. 0. 性能诊断类型 ...

  9. Single Application

    如果限制一个程序同时只能启动一个实例,有几个可以使用的库 QtSingleApplication 以前可以免费使用,后来只有商业版能里能用,在 Github 上也有一个 LGPL 协议的实现,地址为h ...

  10. html5 页面元素插件

    1. 滚动条 jquery.nicescroll 正常引用方式: 设置区域高度 var bodyHeight = $(document.body).height(); $("#XXXXXXX ...