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.pswp.cn/news/712602.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/712602.shtml
英文地址,請注明出處:http://en.pswp.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 …