告别混乱的页面弹出窗口
对于一些快速迭代的产品,尤其是移动C端产品,基于用户操作的目的,在app首页向用户展示各种弹出窗口是非常常见的。在产品初期,由于迭代的版本和运营策略。变化不是太大,可能感觉没什么,但是当产品处于运营后期,各种不能被流言打败的运营策略轮番登场,弹窗的风格和逻辑多次改变,问题就来了。
由于前期缺乏规划,首页可能会出现十多个甚至更多的弹出组件,不仅是首页,首页中引入的子组件也可能超过十个。这些子组件中也有子组件,子组件的子组件也有弹出窗口。每个弹出窗口都有一组相应的控制显示逻辑,分散在多个组件和方法中。但是主页只有一个页面,不能让所有符合显示条件的弹出窗口都出现。
而往往当你意识到这一点的时候,很有可能当情况发展到无法控制的时候,你就无法治愈了。让我们等待死亡
场景:a弹出窗口和b弹出窗口位于主组件,c弹出窗口位于主组件的子组件c,d弹出窗口位于主组件的子组件b,e弹出窗口位于主组件的子组件f的子组件g
PM:希望第一次进入这个页面的时候,只有A弹出窗口、B弹出窗口、C弹出窗口不显示的时候,才会显示D弹出窗口。如果已经显示了D弹出窗口,则在任何情况下都不会显示E弹出窗口,除非再次显示B弹出窗口。
稍微想一想,其实这并不难,只需交给后端通过界面控制所有弹出窗口的显示和隐藏即可,主要是架构的超前规划和低耦合的代码逻辑
弹出窗口的配置
首先,确定一个总体思路。首先,您必须清楚地知道当前页面共享了哪些弹出组件,包括页面的子组件以及子组件内的弹出组件。否则,你甚至不知道如何精确控制哪些组件。所以,还是上面那句话。提前计划,防患于未然是非常重要的。否则,当页面迭代几十个版本时,编写代码的人都走了,你会想到数一数页面上有多少弹出窗口。那真的足够你喝一壶了。
然后,您需要将所有这些弹出窗口记录在一个地方,以便于管理,这样您就可以获得以下数据结构:
//modalMap.jsexport default {//在主页的索引页中记录弹出项index : { Modallistit :[{ name : ' Modal _ 1 ',level: 10,show: true}。{ name: 'modal_2 ',level: 22,show: true },{ name: 'modal_3 ',level: 70,show: true }],childs : { child 1: { modallis t :[{ name : ' modal _ 1 _ 1 ',level 3: 8,show: true },{ name 3: ' modal _ 1 '.还可以继续记录其他页面的弹出结构}modalMap.js文件记录每个页面中的所有弹出项,例如index中的弹出项都是属性名索引的值数据结构。索引页的主要组成部分有两个模态,分别命名为模态1和模态2。如果索引页主组件的子组件中有模态,则继续嵌套。例如,如果index的主分量的子分量child1中有modal,那么就把child1放到index的子分量中继续录制,以此类推
这个结构看起来很清晰,主构件中的模态和主构件中的子构件一目了然。当然,你不能用这个结构,完全由你决定,所以这里暂时定义一下
除了名称,每个模式都有级别和显示属性
Level用于标识当前模态的级别,正常情况下每页只能同时显示一个模态。但是如果同时有多个模态满足显示条件,比较它们的级别值,哪一个更大,其余的忽略,消除了一个页面可能提示显示多个弹出窗口的情况;
show属性位于modal内部,用于确定是否最终显示modal,因此无论外部条件如何,都很容易通过配置禁用弹出窗口的显示
通过发布/订阅模式管理弹出窗口
弹出窗口的配置结构已经确定,下一步是管理这些配置
一般情况下,多个页面满足条件需要同时显示的场景,大多发生在刚进入页面之后,页面发出多个请求,这些请求的返回结果分别控制相应弹出窗口的显示
因为这些请求很可能在不同的业务线或部门管辖之下,相互独立,所以把弹出窗口的控制权交给后端其实有点难。此外,请求是异步的,前端不容易使用意大利面代码来保证弹出窗口之间的互斥。当页面上迭代几十个以上的弹出窗口时,如果没有提前规划,很容易同时显示弹出窗口。
这里暂时以刚进入页面的情况为例进行逻辑梳理
首先,我需要知道在我第一次进入页面时,页面上可能会弹出哪些弹出窗口(即通过界面控制单个弹出窗口的显示),然后在弹出窗口的所有数据都已经获取(即与弹出窗口相关的界面已经返回数据)时,显示弹出窗口。
这种情况更适合使用发布者/订阅者模式。单个接口的数据返回是一个订阅。当所有接口都被订阅后,就会被发布,也就是弹出显示
//modalmanage . js class modalmanage { constructor(modalllist){ this。modalllatmap={ }这。modal list=modal list }//.}通过modalmanage类管理弹出窗口。初始化时,这个类会收到一个参数modallst,它实际上是进入页面时页面上显示的所有可能的弹出窗口(包括子组件的弹出窗口)的名称集,也就是说,需要知道页面上可能同时显示多少个弹出窗口。以上面的示例代码modalMap.js为例,索引页的modallst值为['modal_1 '。modal _ 2’、‘modal _ 3’、‘modal _ 1 _ 1’、‘modal _ 1 _ 2’、‘modal _ 1 _ 1 _ 1’、‘modal _ 1 _ 1 _ 2’
其实这里直接转移弹窗数量就够了。索引中有7个可能同时显示的弹出窗口,可以直接转移7个。之所以要在这里转移名字,其实是为了方便调试。比如代码出错,页面上其实有5个界面可以控制5个弹出窗口的显示,但是你只订阅了4次。如果只是转号,需要一个一个找出来,看哪一个忘记订阅了,但是如果转名字,就会突然。
当确定页面上任何弹出窗口的状态(即是否满足显示条件)时,将执行订阅操作:
//modalManage.jsadd (name,dataInfo) { //level,handler if(this . modallist . indexof(name)!==-1) { if(!this . modalflatmap[name]){ this . modalflatmap[name]=datainfothis . notify()} else { console . log('重复订阅')}} else {console.log('无效订阅')}} This.modalFlatMap用于记录订阅列表。当订阅列表的长度与modalList相同时,意味着所有弹出窗口都准备好了,可以根据这些弹出窗口的优先级进行显示,也就是notify方法应该做什么。
在notify方法中,首先排除属性show为false的弹出项,然后比较其余弹出窗口的级别,只显示级别最大的弹出窗口:
//modalmanage . jsnotify(){ if(object . keys(this . modalflatmap))。length===this . modallist . length){ const highlevelomodal=object . keys(this . modalflatmap)。过滤器(键=this . ModalFlatMap[键]。显示)。reduce((t,c)={返回this.modalFlatMap[c]。t.level?this . modalflatmap[c]:t//this { level :-1}仅用于给reduce函数一个initialValue,模式项的级别应大于该initialValue的级别值,即-1 }、{level: -1})高级模式. handler ()}}使用singleton模式管理嵌套组件和
上面的ModalManage类足以管理弹出窗口,但还是有问题。如果页面上的弹出窗口分散在主组件及其子组件中,甚至子组件的子组件中,该怎么办?
此时,您需要使用单个案例
//singleton management const manageTypeMap={ }//get singleton function createmadalmanage(type){ if(!manageTypeMap[type]){ manageTypeMap[type]=new ModalManage(getAllModalList(modalMap[type])}通过创建ModalManage返回manageTypeMap[type]} CreateModalManage实例,并根据传入类型决定是否创建新实例。如果单实例管理对象manageTypeMap中没有类型的实例,则创建一个新的ModalManage实例,将其存储在manageTypeMap中,并返回这个新实例;否则,在manageTypeMap中返回创建的实例。
这样,无论弹出窗口中有多少组件是分散的,这些组件嵌套有多深,都可以在保证低代码耦合的前提下成功订阅/发布事件
这里的getAllModalList方法是一个工具方法,用于从modalMap中获取页面对应的弹出数据结构:
//util . jsconst getAllModalList=modaliffo={ let currentList=[]if(modaliffo . modallist){ currentList=currentList . concat(modaliffo . modallist . reduce((t,c)=t.concat(c.name),[])} if(modaliffo . childs){ currentList=currentList . concat(object . keys(modaliffo . childs))。reduce((t,C)={ return t . concat(getallmodallist(modalifo . children[C])},[])} return current list }至于createModalManage的参数类型,其值可以是字符串。例如,如果需要管理主页索引上可能同时显示的所有弹出窗口,可以将type的值指定为index,在index的主组件及其包含弹出窗口的子组件中,可以通过该字段获取ModalManage singleton对象:
const ModalManage=createModalManage(' index ')这也解决了另一个问题,即多个页面的弹出管理。索引页通过索引创建modalmanage单个实例,详细信息页可以通过详细信息创建modalmanage单个实例。双方互不干涉对方的总结
以上示例代码都已经上传到github了,有兴趣的可以看看。
本文只分析弹窗的具体情况。其实应用到其他场景也是可行的,比如页面上同位置浮动挂件的管理。无论是对弹窗还是挂件的管理,都是对mvvm框架中数据的管理。主流前端框架对于复杂的数据管理有相应的解决方案,如vuex、redux等。这些解决方案肯定能解决上述问题。
本文主要讨论这个概念,并探索一个通用的解决方案。无论是使用vue、react、angular还是jquery,还是微信小程序、支付宝小程序、快捷应用等。它可以很容易地插入并以低成本使用。
以上是边肖告别混乱页面弹出的介绍,对大家有帮助。如果你有任何问题,请给我留言,边肖会及时回复你。非常感谢您对我们网站的支持!
版权声明:告别混乱的页面弹出窗口是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。

















