美文网首页
入坑React之五 框架修改经验之多TAB

入坑React之五 框架修改经验之多TAB

作者: 松鼠杨 | 来源:发表于2017-04-13 10:54 被阅读859次

    由于是管理系统,多标签页应该算是一个常用方式。有了多标签页,使用者在使用这个系统进行日常工作时,就可以在同一个页面中进行多个业务功能模块之间切换,不必重新去找各个同的业务菜单重新打开。而且已经打开的tab页来回切换时,能各自保持原状态。

    Ant Design 提供了TAB组件,我们就想办法看看如何引进来。

    菜单必须有,这是用户寻找业务功能的入口。如果使用多tab,那么菜单点击的时候要完成两件事:

    • 如果当前没有对应的标签页,就新打开一个
    • 如果当前已经有了对应的标签页,就切换到那个标签页上

    但是,在传统方式下,菜单上的链接是Link组件生成的,这个Link是路由提供的组件,用它生成的链接点击效果是:会激活路由,然后找到对应的Component,然后将这个组件作为children,传给该路由所在的父组件。然后,父组件重新渲染自己,把这个children放到对应的地方就好了。

    如果有多TAB,就不能这么玩了。

    我认为,我们必须有一个全局的tab列表,用来保存已经打开的tab。每个tab都有key的。然后有个对象用来记录当前活跃的tab的key。

    所以,修改为:菜单点击的时候,还是走路由的那一套,拿到children,传给父组件。但是父组件就先别加载它了。

    那父组件怎么做呢?

    1. 对于菜单增加点击事件,点击的时候,将菜单的url作为key,push进全局的tab列表。
    2. 对于菜单的点击事件,可以拿到当前活跃的location和children(注意拿到的是点击菜单之前的),不过这也没关系,起码location和children组件的对应关系是正确的。我们可以把location中的url提取出来,拿来和在tab列表中的key们对比,如果已存在,就将对应的key和这个children对应上,就完成了菜单项和里面的组件的对应。
    3. 但是,你肯定就会问了,这也的话,新打开的标签,从tab列表中找组件,肯定找不到啊。没关系,新打开的时候,除了点击事件,也走了路由了,也会将新路由对应的children组件传进来,我们在组件渲染的时候,直接将这个组件放到tab中就好了。
    4. 组件渲染:路由点击事件触发父组件重新渲染,同时传入children。所以,我们在父组件渲染的时候,生成TAB。根据tab列表中的元素生成所有标签页,活跃的标签页是根据当前活跃页的那个对象值确定。然后,如果这个列表中有children的,就把children放进去,如果没有children的,就拿父组件中当前的children放到标签页中去。
    5. 对于关闭还有切换的处理,注意写一下就好。

    那到底具体是怎么实现的呢?

    1. 增加全局变量tabList。这是个对象,共其他文件用import方式引用。它里面包含一个列表,列表项是每个菜单的信息:包括key,name即标签上的中文显示名,children即tab页中的children组件,location,即该tab对应的location。
    2. 侧边栏的Menu组件传入点击事件方法。点击事件的方法在容器组件中实现。即,上面提到的父组件。这个方法接受当前链接为入参,同时获取到点击之前的当前children和location。然后dispatch到model中的新增tab方法实现。
    3. model中的新增tab方法:更新currentTab、判断tabList:如果没有就push进一个新的进去,如果没有children就把children放进去。并且判断当前是不是一个tab都没有。(如果没有tab,父组件渲染的时候会加载欢迎页)
    4. 在model中做了关闭tab的方法:与上面那个方法差不多相反,需要适当的从tablist中删元素。currentTab的设定原则是:如果关的不是活跃页则不变。如果关闭了活跃页,则找list中的它前面那个设为活跃页。

    其他细节:

    用routerRedux.push方式带参数进行路由重新调用时,期待是走一下model中的注册的方法,即用户点击业务菜单目录url后进行一次查询。这没问题。问题是,正常情况下,用户再点击目录菜单,则会进行一次无参数查询,这会导致我们的标签页的内容重置。如何防止?我的做法是:

    • 在目录中生成的链接url中,拼装上requery=false。当点击菜单时,所有requery是false的不查询。但是有例外:如果这时候这个菜单在tablist中没有children,那也是需要查一次的。
    • 如果业务需要routerRedux.push的方式引发查询,那么一定要把requery设为true。
    • 当requery是true的时候,如果没有children,也是不查的。因为如果你直接用requery=true来访问,而页面上是默认刷新的,这时没有标签页的,如果查了反而是浪费。
    • 后来又做了和目录的联动、以及解决iPad上点击目录时tab内容不正确的问题。

    相关文章

      网友评论

          本文标题:入坑React之五 框架修改经验之多TAB

          本文链接:https://www.haomeiwen.com/subject/ydfbattx.html