致虚极 守静笃
Ant Design Pro页面内切换组件问题
2020-09-12发布 113

目的

最近在项目中要使用Ant Design Pro,页面布局大致如图:

layout

在详情页中需要显示非常复杂的数据,想要的效果是点击主要内容区域的tab可以切换到对应的详情内容。

问题

我们在每个页面中都使用了框架提供的PageHeaderWrapper这个组件,如上图的详情规则这两个tab,但是可能是因为我们使用的版本比较老,一直没搜到这个组件相关API的信息,只了解到可以通过向PageHeaderWrapper提供tabList这个props来显示TabtabActiveKey设置激活的Tab,同时有onTabChange这个回调。

现在点击切换Tab已经可以实现,但是如何让内页面主要内容随着Tab切换而改变呢?我对前端还不够熟悉,对Ant Design Pro的路由了解也不深,大概想到这么几个办法:

  1. 在框架规定的config.js中配置路由,添加多个路由,Tab下包含Link,点击切换到对应页面
  2. 维护一个state,不同的详情组件都放在PageHeaderWrapper中,切换Tab改变组件的display属性
  3. 直接用state维护子组件,切换Tab改变state,实现子组件的切换

由于要切换显示的详情内容其实都来自同一个API一次提供的数据,如cloth/1,这里面可能包含了很复杂的数据,只是为了在视觉显示上区分开来,如果采用方法1,似乎就要有三个不同的页面,每个页面都要单独请求一次后端数据,方法2和3思路差不多,都是通过state来动态改变显示效果,但是总觉得实现起来不够优雅,会给后期维护带来麻烦。主要还是对前端了解不够深。

最终解决方案

参考了一篇文章,感觉我可以结合思路2、3与ReactSuspense来做。

import React, { Suspense } from 'react';

const OtherComponent = React.lazy(() => import('./OtherComponent'));

function MyComponent() {
  return (
    <div>
      <Suspense fallback={<div>Loading...</div>}>
        <OtherComponent />
      </Suspense>
    </div>
  );
}

如上,可以借助React.lazy实现动态引入,并将这种“懒加载”的组件包裹在Suspense中渲染,最终我的实现方法大致如下:

// 省略多余代码,将tab切换后的key值塞入state中
const handleTabChange = key => {
    this.setState({activeKey: key})
}

render() {
    // 省略
    const { activeKey } = this.state
    const Child = React.lazy(() => import(`./${activeKey}`))
    return (
        <PageHeaderWrapper ......>
            <Suspense fallback={<div>Loading...</div>}>
                <Child data={data} />
            </Suspense>
        </PageHeaderWrapper>
    )
}

以上是大致的实现,主要就是根据切换tab后的key值,动态引入对应的子组件并渲染。主要就是为了将不同的模块分离开,提高复用性吧。当然我的做法可能有问题,毕竟对ReactAnt Design Pro了解还不够深入,权当抛砖引玉了。

思考

在实践的过程中,经常有可能只是要写个简单的功能,我们会随意写个函数,最终随着功能的复杂化,可能我们的代码量越来越大,有时候就会见到“超级文件”、“超级函数”这样的代码,给维护和复用带来很多困难。其实对于工程实践中的问题,我们常常听到很多名词,诸如面向对象、函数式编程、模块化编程、TDD,以及语言层面,例如JavaScript的超集TypeScriptPython中的类型注解,Rust所有权等等,很多东西在项目前期往往看不到好处,反而让程序员觉得浪费时间,但是也许在后期这些东西能避免很多问题。但是也常有人说,不要过早优化,如何权衡或者说掌握好项目进度与代码优化的之间的平衡,这是个值得思考的问题。