上述的 ModalManage类已经足以管理弹窗了,但还有个问题,如果一个页面上的弹窗,分散位于页面主组件及其子组件,甚至是子组件的子组件内,怎么办?
这个时候就需要使用单例了
// 单例管理
const manageTypeMap = {}
// 获取单例
function createModalManage (type) {
if (!manageTypeMap[type]) {
manageTypeMap[type] = new ModalManage(getAllModalList(modalMap[type]))
}
return manageTypeMap[type]}通过 createModalManage这个方法来创建 ModalManage实例,根据传入的 type来决定是否创建新的实例,如果单例管理对象 manageTypeMap中不存在 type对于的实例,则 new一个 ModalManage实例,存入 manageTypeMap中,并返回这个新实例,否则就返回 manageTypeMap中已经创建好了的实例
这样一来,无论弹窗分散在多少个组件内,无论这些组件嵌套得有多深,都能够在保证代码低耦合的前提下,顺利地订阅/发布事件
这里的 getAllModalList方法是个工具方法,用于从 modalMap中获取页面对应的弹窗数据结构:
// util.js
const getAllModalList = modalInfo => {
let currentList = [] if (modalInfo.modalList) {
currentList = currentList.concat(
modalInfo.modalList.reduce((t, c) => t.concat(c.name), [])
)
}
if (modalInfo.children) {
currentList = currentList.concat(
Object.keys(modalInfo.children).reduce((t, c) => {
return t.concat(getAllModalList(modalInfo.children[c]))
}, [])
)
}
return currentList
}至于 createModalManage的参数type,其值可以就是一个字符串,例如如果需要管理首页 index上可能同时展示的所有的弹窗,则可以将 type 的值指定为 index,在 index主组件以及其包含弹窗的子组件内,都通过这个字段来获取 ModalManage单例对象:
const modalManage = createModalManage('index')这样做同时也解决了另外一个问题,就是多个页面的弹窗管理问题,index页面通过 index创建 ModalManage单例,详情页就可以通过 detail来创建 ModalManage单例,双方互不干扰
总结
上述所有示例代码已经上传到 github,有兴趣地可以看下
本文只是对弹窗这么一种具体的案例进行分析,实际上应用于其他场景,例如页面同一个位置的悬浮挂件管理等都是可行的
无论是弹窗的管理还是挂件的管理,放在 mvvm框架中,都是数据的管理,主流前端框架对于复杂的数据管理,都已经有对应的解决方案,例如 vuex 和 redux等,这些解决方案当然也能够解决上面的问题
本文主要是对这种理念的探讨,探讨出一种通用的解决方案,无论你用的是 vue、react、angular还是jquery一把梭,亦或是微信小程序、支付宝小程序、快应用等,都可以低成本地轻松套入使用










