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

在前端的有些场景中,我们需要进行组件间的通信,一般而言,我们可以采用的手段有很多,比如: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工作流

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

相关推荐
wordbaby4 分钟前
TanStack Router 基于文件的路由
前端
wordbaby9 分钟前
TanStack Router 路由概念
前端
wordbaby11 分钟前
TanStack Router 路由匹配
前端
cc蒲公英12 分钟前
vue nextTick和setTimeout区别
前端·javascript·vue.js
程序员刘禹锡17 分钟前
Html中常用的块标签!!!12.16日
前端·html
sinat_3842410923 分钟前
OpenSpeedy 是一款开源免费的游戏变速工具
javascript
我血条子呢27 分钟前
【CSS】类似渐变色弯曲border
前端·css
DanyHope28 分钟前
LeetCode 两数之和:从 O (n²) 到 O (n),空间换时间的经典实践
前端·javascript·算法·leetcode·职场和发展
hgz071029 分钟前
企业级多项目部署与Tomcat运维实战
前端·firefox
用户18878710698429 分钟前
基于vant3的搜索选择组件
前端