Vue中的事件总线(EventBus)是什么?它有什么优点和缺点?

作为一名使用Vue的前端开发者,有时候会听到事件总线(EventBus)这个名词。但可能是我入行比较晚,我在Vue网站中并没有看到过事件总线的介绍,在项目中也没有使用过。那究竟什么是事件总线?事件总线可以解决什么问题?

事件总线简介

事件总线是一种组件通信方式,用于在工程的中的任意组件中进行事件触发和数据传递。

通过在全局创建一个事件总线,所有组件(无论他们的关系是父子还是兄弟还是不相关)都可以使用同一个总线发送事件和监听事件,传输数据。这样通信就可以不受组件间关系限制,实现灵活的通信能力。

Vue2实现事件总线

创建总线

首先创建一个Vue2项目,可以使用Vue CLI。然后在src/main.js中创建一个事件总线。创建的方式有两种:

  1. 新创建一个Vue实例
import Vue from 'vue'
import App from './App.vue'Vue.prototype.$EventBus = new Vue()
new Vue({ render: h => h(App), }).$mount('#app')
  1. 使用已有的Vue实例
import Vue from 'vue'
import App from './App.vue'new Vue({render: h => h(App),beforeCreate() { Vue.prototype.$EventBus = this; }
}).$mount('#app')

触发/接收事件

我们假设有两个组件A和B,A触发事件,B接收事件。

  • 组件A
<template><div> <p @click="add"> 点击增加 </p> </div>
</template>
<script>
export default {name: 'Add',data() { return { sum: 1, addNum: 1 } },methods: {add() {this.sum += this.addNum;this.addNum++;this.$EventBus.$emit('add', this.sum);}}
}
</script>
  • 组件B
<template><div> <h1>收到数据: {{ sum }}</h1> </div>
</template>
<script>
export default {name: 'HelloWorld',data() { return {sum: 1,listenFun: (sum) => { this.sum = sum; }}},mounted() {this.$EventBus.$on('add', this.listenFun)},beforeDestroy() {this.$EventBus.$off('add', this.listenFun)},
}
</script>

可以看到事件总线的实现方式实际上非常简单,就是把一个Vue实例挂载为一个全局属性,在这个实例上触发事件,监听事件即可。如果不需要监听时,要记得销毁监听事件。

其它组件通信方式

Vue2有很多组件间的通信方式,这里总结一下:

  1. 组件Props 父组件向子组件传递数据
  2. 组件事件Emit 子组件触发事件;父组件监听事件,接收数据
  3. 组件v-model 通过props和事件实现父子组件数据的双向绑定
  4. 依赖注入 父组件向后代组件传递数据
  5. Attributes 没有被组件声明为props或emits的属性;父组件向子组件传递数据
  6. 状态管理 全局共享的数据管理,一般使用Pinia或者Vuex等工具
  7. 事件总线 全局组件共享的事件管理
  8. 模板引用ref 父组件主动调用子组件方法,可传递数据
  9. 其它方式 可以存放数据的公共位置,比如Storage, Window等。

事件总线的优缺点

通过事件总线的实现,我们可以了解到事件总线可以非常简单的实现全局组件共享的事件管理,传递数据等。既然如此简单,那Vue为什么没有推荐作为官方的组件通信方式?为什么即使Vue官方并无推荐,但却有很多开发者使用事件总线。我们结合上面的其它组件通信方式,来讨论下事件总线的优缺点。

优点

  1. 实现全局任意组件共享的数据传输
    查看上面的通信方式,我们可以看到Vue提供的大部分方式都有组件关系的限制,大部分是父组件向子组件向后代组件之间传递。而事件总线却没有任何限制。
  2. 实现非常简单
    使用状态管理工具也可以实现数据传递,但是这些工具都要引入依赖库,有自己的使用方式。虽然并不麻烦,但是都没有事件总线使用这么简单。
  3. 全局的事件管理器
    组件通信除了传递数据,另一个作用是实时触发事件,针对事件进行操作。查看上面的组件通信方式,我们发现除事件总线外,全局的通信只是数据的传递,没有事件的触发。通过监听状态管理和Storage数据等,可以变相实现事件的管理,但是并没有事件总线清晰和直接。

缺点

  • 事件监听只能被动接收数据,不能随时获取状态
    如果需要随时获取状态,显然还是状态管理工具更适合。
  • vue3不提供事件总线能力
    在vue3中$on $off等实例方法已被移除,组件实例不再实现事件触发接口。官方推荐使用 mitt 等外部工具。

还有使用不慎带来的很多问题。例如:

  • 事件名共享同一个命名空间
  • 不销毁事件监听器
    如果在不使用后忘记销毁事件监听器,会造成难以排查的Bug或者引发性能问题。
  • 误销毁同名事件其它监听器
    比如多个组件都监听了同一事件’add’。其中某个组件销毁了’add’事件下的所有监听器this.$EventBus.$off('add'),就会影响其他的组件。
  • 其它问题 例如调试困难,耦合性高等等。

总结

事件总线作为一种全局的组件通信方法,符合订阅发布模式,由于其简单有效的使用方式,受到部分开发者的欢迎。但是由于各种使用不慎和维护带来的问题,官方和许多开发者也不推荐使用:

在绝大多数情况下,不鼓励使用全局的事件总线在组件之间进行通信。虽然在短期内往往是最简单的解决方案,但从长期来看,它维护起来总是令人头疼。根据具体情况来看,有多种事件总线的替代方案. —— Vue3迁移指南

但是事件总线就完全不能使用么?也并不是。首先上面说的各种使用问题,可以通过预先制定开发规范+严格代码审核解决。其次,查看上面的通信方法,其实Vue并没有直接的全局事件通知方式,作为一种全局事件通知工具,还是有它独特的作用的。是否可以使用,还是要具体问题具体分析。

参考

  • Vue3迁移指南 事件API
    https://v3-migration.vuejs.org/zh/breaking-changes/events-api.html
  • mitt —— Tiny 200b functional event emitter / pubsub.
    https://github.com/developit/mitt

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/712602.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

element-plus表格合并

要实现这样的表格&#xff0c; 怎么做呢&#xff1f; 甚至是这种三级的呢&#xff1f; 官网的案例也是通过这个方法进行配置的&#xff0c;也就是说表格长什么样&#xff0c;关键在怎么处理的方法上。 这是官网的方法&#xff0c;可参考拓展&#xff1a; const arraySpanMeth…

一款云渗透工具 - Sea Moon

SeaMoon - 月海 什么是月海 &#x1f315; 月出于云却隐于海 月海(Sea Moon) 是一款 FaaS/BaaS 实现的 Serverless 网络工具集&#xff0c;期望利用云原生的优势&#xff0c;实现更简单、更便宜的网络功能。 月海之名取自于苏轼的《西江月顷在黄州》&#xff0c;寓意月海取自…

【JVM】JVM相关机制

1. JVM内存区域划分 1.1 内存区域划分简介 内存区域划分&#xff1a;实际上JVM也是一个进程&#xff0c;进程运行时需要向操作系统申请一些系统资源&#xff08;内存就是典型的资源&#xff09;&#xff0c;这些内存空间就支撑着后续Java程序的运行&#xff0c;而这些内存又会…

Python环境搭建:一站式指南

在当前AIGC技术蓬勃发展的背景下&#xff0c;Python作为人工智能领域最受青睐的编程语言之一&#xff0c;成为我们必须掌握的技能。因此&#xff0c;搭建一个适合自己的Python环境成为了每个Python开发者的首要任务。本文将为您提供一站式的Python环境搭建指南&#xff0c;帮助…

PythonOpenCV随机粘贴图像

import cv2 import numpy as np import random # 读取两个图像 image1 cv2.imread(image1.jpg) image2 cv2.imread(image2.jpg) # 将image1转换为灰度图像 gray_image1 cv2.cvtColor(image1, cv2.COLOR_BGR2GRAY) # 创建掩码&#xff0c;黑色部分为0&#xff0c;非黑色部…

Python自动发邮件

我经常需要用手机看服务器的运行情况&#xff0c;所以就写一个脚本&#xff0c;通过邮件把服务器运行情况发送给我&#xff0c;直接手机可以查看炼丹状态。事实证明还是很有用的&#xff0c;所以撰写一篇博文将脚本分享给大家。这里用到smtplib和email两个python包。 import s…

力扣精选算法100道——颜色分类(双指针和三指针俩种方法解决此题)

目录 &#x1f6a9;了解题意 &#x1f6a9;算法分析 第一种方法&#xff1a;双指针 &#x1f6a9;代码实现一 第二种方法&#xff1a;三指针 &#x1f6a9;代码实现二 &#x1f6a9;了解题意 本题将整数0&#xff0c;1&#xff0c;2代表红白篮&#xff0c;nums中的整数并…

仿牛客网项目---私信列表和发送列表功能的实现

这篇文章我们来讲一下我的这个项目的另外一个功能&#xff1a;私信列表和发送列表功能。 先来设计DAO层。 Mapper public interface MessageMapper {// 查询当前用户的会话列表,针对每个会话只返回一条最新的私信.List<Message> selectConversations(int userId, int of…

【激光SLAM】基于已知位姿的构图算法 (Grid-based)

文章目录 地图分类概念 覆盖栅格建图算法栅格地图的特征数学描述假设 算法流程激光雷达的逆观测模型 计数(Count Model)建图算法概念数学描述观测模型地图估计 地图分类 概念 地图即为环境的空间模型。环境地图是机器人进行定位和规划的前提。定位可以用特征地图&#xff08;…

可穿戴设备相关Python包【待更】

提供7个python 包。 1 2 3 4 5 6 7 pyActigraphyGitHub - ghammad/pyActigraphy: Python-based open source package for actigraphy data analysisActiGraph ActiGraph GitHub

基础内容哦!!!吴恩达deeplearning.ai:利用计算图求导(反向传播)

以下内容有任何不理解可以翻看我之前的博客哦&#xff1a;吴恩达deeplearning.ai专栏 文章目录 一个小型神经网络的例子利用计算图逐步计算价值函数J利用计算图求出价值函数的导数 计算图是深度学习中的一个关键概念&#xff0c;它也是Tensorflow等编程框架自动计算神经网络导…

Linux之sed命令详解及实践

1、定义 sed全称是&#xff1a;stream editor 流编辑器 对文件的操作无非就是”增删改查“&#xff0c;**sed命令就是实现对文件的”增删改查“。** **man sed//man 的解释** 用于过滤和转换文本的流编辑器 2、功能 Sed 主要用来自动编辑一个或多个文件、简化对文件的反复…

实现定时器的两种方法:使用windows api定时器 和使用c++11/14 定时器

前言&#xff1a; 当我有一个开发需求&#xff0c;符合下面的条件 1.需要某个任务在程序中每隔一段时间就要执行一次&#xff0c;可能把这个任务封装成了一个函数。 2.这种需要定时执行的任务&#xff0c;有2个&#xff0c;3个....越来越多。 这个时候我们就可以考虑使用定时…

iOS高级理论:常用的架构模式

一、常用的架构模式简介 在 iOS 开发中&#xff0c;常用的架构模式有以下几种&#xff1a; MVC&#xff08;Model-View-Controller&#xff09;模式&#xff1a;是 iOS 开发中最常见的架构模式。在 MVC 模式中&#xff0c;Model 负责数据处理和业务逻辑&#xff0c;View 负责界…

Tcl文件访问

1. 基本文件输入输出命令 open 文件名 方式 set f [open $filename "r"] f 是文件的通道ID,可以使用open命令打开文件并获取通道ID r 只读方式打开,文件必须已经存在 r+ 读写方式打开,文件必须已经存在 w 只写方式打开文件,如果文件存在则清空文件内容,否则创建…

第三百七十六回

文章目录 1 .概念介绍2. 实现方法3. 示例代码 我们在上一章回中介绍了在页面之间共传递数据相关的内容&#xff0c;本章回中将介绍如何拦截路由.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1 .概念介绍 本章回中介绍的路由拦截是指在路由运行过程中&#xff0c;对路由做…

会了会了会了

public class text9 {/*在实际开发中&#xff0c;如果我们需要在多种情况中选择其中一个,就可以用switch语句。当我m们拨打电话&#xff0c;会有一些按键选择。假设我们拨打了一个机票预订电话&#xff0c;电话中提示&#xff1a;1机票查询2机票预订3机票改签4退出服务其他按键…

论文阅读_代码生成模型_CodeLlama

英文名称: Code Llama: Open Foundation Models for Code 中文名称: Code Llama&#xff1a;开放基础代码模型 链接: https://arxiv.org/abs/2308.12950 代码: https://github.com/facebookresearch/codellama 作者: Baptiste Rozire, Jonas Gehring, Fabian Gloeckle, Sten So…

【前端素材】推荐优质在线花卉商城电商网页Flowery平台模板(附源码)

一、需求分析 1、系统定义 在线花卉商城是一个通过互联网提供花卉销售服务的电子商务平台&#xff0c;用户可以在该平台上浏览、选择和购买各种花卉产品。 2、功能需求 在线花卉商城是一个通过互联网提供花卉销售服务的电子商务平台&#xff0c;用户可以在该平台上浏览、选…

vscode在windows环境不能使用终端安装依赖

会报这样的错误提示 解决思路&#xff1a; 1、vscode用管理员打开 (非必须) 2、设置策略 打开 windows powerShell . 输入命令 set-ExecutionPolicy RemoteSigned 然后 Y . 查看是否设置成功 get-executionpolicy 3、下载总是超时&#xff0c;设置镜像源 查看镜像源 npm …