实现一个简易的可回复广播事件,优雅解决跨组件问题

在前端的有些场景中,我们需要进行组件间的通信,一般而言,我们可以采用的手段有很多,比如:react的context、redux等等,他们可以跨组件共享数据。如果说我们的通信只是进行数据同步的话,那么现有方案能很好的处理此类问题。

但是,现在我们的场景不涉及数据同步,我们只想向需要我的组件告知我的动作。比如,我们有一个需求如下:

有一个窗口,这个窗口是用来预览各种文件的,并且我们可以对文件进行评论。现在有一个小功能,就是在关闭窗口的时候,需要判断一下有没有未提交的评论,如果有的话,就询问一下,是否需要提交评论?是提交后关闭窗口,还是先不关闭窗口,继续编辑评论

这个小需求其实有多种实现方式

一、第一种的方式,可以把评论数据放到store里面,然后在关闭窗口的组件读取 store 里面的评论数据,根据数据进行判断。

这个方式虽然能实现需求,但是它有几个问题:

  • 关闭组件和评论组件耦合了,在关闭组件中做了评论的业务处理。如果在关闭窗口的时候,还有类似的业务需要处理,那么这个关闭窗口的逻辑将会变得臃肿
  • 二是对于评论数据,这里不需要写到store中,因为他暂时还不是一个需要全局消费的数据

二、第二种方式呢,是在关闭窗口的时候,发出一个广播,如果某个组件需要根据这个关闭事件做一些处理的话,就可以监听这个事件,然后根据自身的业务逻辑,给广播发送源一个结果,广播发送源根据返回结果,来决定执行对应的结果,在这里,广播发送源就是关闭组件了

第二种方式跟第一种相比的话,组件之间不再耦合了,每个组件都只需要关注自己的业务逻辑就好了,比如关闭组件,它只需要根据收到的结果执行关闭或者不关闭,至于这个结果是依据什么业务逻辑得到的,它是不需要关心的。

那么以往我们使用的广播,都是只能监听到相应的事件,广播接收方并不能决定广播发送方的逻辑。今天实现这个小需求的关键就是在基础广播的基础上,加上"回复"功能

先实现一个广播,广播的话,使用发布订阅模式就好了,这里不多说,最基本的三个事件如下:

js 复制代码
const eventMap = {}
addEvent(eventName, fn) {
    // 添加事件
    if (eventMap[event]) {
      eventMap[event].push(fn)
    } else {
      eventMap[event] = [fn]
    }
}
sendEvent(eventName, val) {
    // 发送事件
    if (this.eventList[event]) {
      this.eventList[event].forEach((fn) => fn(val))
    }
}
removeEvent(event: string, fn) {
    // 移除事件
    if (!eventMap[event]) return
    eventMap[event] = eventMap[event].filter((f) => f !== fn)
}

以上就是一个基本的广播,如果需要实现一个"可回复 "功能的话,那么自然第一个想到的就是使用promise去实现,我们只需要把保存的监听事件,用promise重新包一下就可以了,代码如下:

js 复制代码
const sendEvent = (event: string) => {
    if (eventMap[event]) {
      const p = eventMap[event].map((fn) => {
        return new Promise((resolve, reject) => {
          fn({ resolve, reject, payload: val })
        })
      })

      return Promise.all(p)
    }
    // 没有广播,直接成功
    return Promise.resolve()
  }

代码很简单,经过改造以后,发出去的广播结果由各个监听事件来决定,并且发送方,也能收到结果,并根据结果做出自己的逻辑。

再回到文章开头的小例子,来看看使用"可回复的广播"是怎么实现的

js 复制代码
addEvent('win-close', (resolve,reject) => {
  if (没有评论){
    resolve()
    return
  }
  
  if (保存评论){
    发起保存请求
    resolve()
  }
})

sendEvent('win-close').then(() => {
  关闭窗口
})

可以看到,关闭窗口这段逻辑,是根据监听事件的结果来决定是否执行的。整个可回复广播大概就是这样了

往期回顾

打造一个优雅的git工作流

怎么自动化处理前后端对接过程?这是一个问题

相关推荐
若年封尘9 分钟前
告别手写 API 类型:用 openapi-fetch 打造类型安全的前端接口层
前端·安全·openapi-fetch
cypking14 分钟前
二次封装ElementUI日期范围组件:打造带限制规则的Vue2 v-model响应式通用组件
前端·javascript·elementui
A923A15 分钟前
【小兔鲜电商前台 | 项目笔记】第二天
前端·vue.js·笔记·项目·小兔鲜
牧码岛15 分钟前
Web前端之样式中的light-dark函数,从媒体查询到颜色函数,从颜色到图片,light-dark打开CSS新时代、主题切换的暗黑模式到image的正解
前端·css·web·web前端
酉鬼女又兒29 分钟前
零基础快速入门前端蓝桥杯Web考点深度解析:var、let、const与事件绑定实战(可用于备赛蓝桥杯Web应用开发)
开发语言·前端·javascript·职场和发展·蓝桥杯·es6·html5
宁雨桥40 分钟前
前端项目实现光暗主题切换的完整方案
前端
happymaker06261 小时前
vue指令扩展以及监视器的使用
前端·javascript·vue.js
还是大剑师兰特1 小时前
EventBus核心方法用法
javascript·vue.js·大剑师
一只小阿乐1 小时前
vue前端处理流式数据
前端·javascript·ai·大模型·全栈开发·agentai
问道飞鱼1 小时前
【技术方案】面向 Web 系统的《全栈灰度部署方案设计》
前端·全栈·灰度发布