前言
最近写的
移动端业务
经常跟弹框
打交道,偶尔处理对于多个弹框的显示
问题也是捉襟见肘
,特别是产品经常改需求
,那么有没有一种优雅的解决方案去处理上面这种问题
,或者说,淘宝
、拼多多
等是怎么处理这种问题的
由于项目一开始没有做好规划
或者说一开始就不是你维护的
,导致首页的弹窗组件可能放了十多个甚至更多
,不仅是首页有,首页内又引入了十多个个子组件
,这些子组件内也有弹框
,另外子组件的子组件也可能存在弹框
,每个弹窗都有对应的一组控制显隐逻辑
,但是你不可能让所有符合显示条件的弹窗都全都一下子在首页弹出来,如何有顺序的管理这些弹框是重中之重
的事情
一个小场景
上面这么分析可能有同学还是不了解这个
业务痛点
,我们举个例子,假设首页页面有个A组件,A组件有一个弹框A_Modal
需要在打开首页显示出来,enen…很简单,我们按照平时的逻辑请求后端接口拿到数据去控制弹框显示
就行,我们继续接着迭代
,此时遇到了一个B组件,同样也是要显示在首页
,因为是新活动,所以优先级比较大
,需要显示B_Modal弹框
,这时候你可能要去找找控制A组件的接口
,找到后端说这个组件不显示了或者说自己手动重置为false
,一个组件可以这样搞,但是几十个呢?,不太现实
如下图:
这些弹框是都要在首页上显示的弹框
小误区
❗️注意以下这种交互弹框不在我们讨论范围之内,比如通过按钮弹出弹框这种,像这类弹框通过
交互事件
我们控制就行,我们要处理的弹框场景是通过后端接口来显示弹框
,所以后面我们所说的弹框都是这种情况
,注意即可
带着这个业务痛点
,我去踩坑了几种方案,下面来分享下以下这种配置化弹框
方案(借鉴了动态表单的思路来实现
)
配置化弹框
之前写
管理后台系统
的时候有了解过动态表单
,实际就是通过一串JSON数据渲染出表单
,那么我们是不是可以基于这种思路,通过可配置化的数据
来控制弹框的显示
,显然是可以的
// modalConfig.js
export default {
// 首页
index: {
// 弹框列表
modalList: [{
id: 1, // 弹框的id
name: 'modalA',
level: 100,
// 弹框的优先级
// 由前端控制弹框是否显示
// 当我们一个活动过去了废弃一个弹框时候,可以不需要通过后端去更改
frontShow: true
}, {
id: 2,
name: 'modalB',
level: 122,
frontShow: true
}, {
id: 3,
name: 'modalC',
level: 70,
frontShow: true
}]
}
}
这样做的好处就是利于管理弹框
,并且最重要的一点,我可以知道我的页面有多少弹框
,一目了然的去配置
,这里我们先讲解下每个弹框modal的属性
id
:弹框id-弹框的唯一idname
: 弹框名称-可以根据名称很快找到该页面上的弹框level
: 弹框优先级-杜绝一个页面可能提示展示多个弹窗的情况frontShow
: 前端控制弹框显示的字段-默认为true
backShow
: 后端控制弹框显示的字段-通过接口请求获取
发布订阅模式来管理弹框
配置完弹框数据,我们还缺少一个
调度系统去统一管理这些弹框
,这时候自然而然就可以想到发布订阅这种设计模式
// modalControl.js
class ModalControl {
constructor () {
// ...
}
// 订阅
add () {
// ...
this.nodify()
}
// 发布
notify () {
// ...
}
}
正常情况下,后端单个接口
会返回给我们字段来控制弹框的显示
,当然也可能存在多个接口去控制
弹框的显示,对于这些情况,我们前端自己去做一层合并
,只要保证最后得出一个控制弹框是否展示的字段就行
,此时我们就可以在相应的位置取注册我们的弹框类即可
那什么时候发布呢
?
注意这里的发布跟我们平时的发布
判断情况可能不一样,以前我们可能通过在一个生命周期钩子或者按钮触发等事件去发布
,但是我们仔细想想,进入首页由接口控制显示
,这样动作的发生需要2个条件
- 每次发生一次订阅操作都伴随着一次执行一次
预检测
操作,检测所有的弹框是否都订阅完
- 真正触发的时机是当前页面的弹框都订阅完了,因为只有这样才能拿到所有弹框的优先级,才能判断显示哪个弹框
第一版实现
根据上面的分析
单个接口返回的就是一个订阅
,而发布是等到所有的弹框都订阅完才执行
,于是我们可以快速写出以下代码结构
class ModalControl {
constructor () {
// ...
}
// 订阅
add () {
// ...
this.preCheck()
}
// 预检测
preCheck(){
if(this.modalList.length === n){
// ...
this.notify()
}
}
// 发布
notify () {
// ...
}
}
实现这个弹框类
,我们来拆分实现这四个方法
就行了
constructor构造函数
根据以上思路,
ModalControl类
的 constructor方法中需要设置的初始值差不多也就知道了
// 上述弹框配置
import