前端组件通信工具-自定义Bus

发布时间 2023-09-26 10:19:36作者: 分页需带参

前端组件通信工具-自定义Bus

在utils添加Bus

// 先定义一个类型,emit作为发布(传递),on作为订阅(接收)
// name是事件名称,callback是一个回调函数
type BusClass = {
    emit:(name:string) => void
    on:(name:string, callback:Function) => void
    off:(name:string) => void
}
// 定义多种参数类型
type PramsKey = string | number | symbol
// 定义一个调用中心,可以接收多个参数
type List = {
   [key:PramsKey]: Array<Function>
}
class Bus implements BusClass {
    list: List
    constructor (){
        // 初始化list
        this.list = {}   
    }
    // 发布事件,...args解构多个参数
    emit (name:string,...args:Array<any>){
        // 获取到list里的数据
        let evnentName:Array<Function> = this.list[name]
        evnentName.forEach(fn =>{
            fn.apply(this, args)
        })
    }
    // 接收事件
    on (name:string, callback:Function){
        // 如果是第一次注册,则为空;如果被多次注册,则采用之前注册的名字
        let fn:Array<Function> = this.list[name] || []
        fn.push(callback)
        this.list[name] = fn
    }
    //卸载事件(每次使用完后需要在组件销毁前,清除事件,否则会多次触发事件)
    off (name:string){
        this.list = {}
    }
}
// 导出bus
export default new Bus()

在需要使用的组件中引入

import Bus from "@/utils/bus";

在任意组件或方法中触发事件

 //searchOpinionData触发事件的名字,标识,searchFrom.value触发事件需要传递的数据
Bus.emit("searchOpinionData", searchForm.value);

触发后接收执行

Bus.on("searchOpinionData", (data) => {
    //做一系列操作1
  searchStr.value = data.search;
  searchType.value = data.treeType;
  currentPage.value = 1;
  getOpinionList();
  // 搜索时,不管是否有数据都渲染(空数据同样渲染)
  isLoading.value = true;
    
});

这样已经基本完成啦

此时存在的问题,多次进入组件再次触发Bus时会多次执行 做一系列操作1中的操作,于是乎在组件卸载前需要卸载bus中的事件

import { onBeforeUnmount } from "vue";

onBeforeUnmount(() => {
  //组件销毁前需要解绑事件。否则会出现重复触发事件的问题
  Bus.off("searchOpinionData");
});