基于 Ant Design Pro 页面标签化展示的研究与实现

2021-05-15 21:00:16 +08:00
 theprimone

效果预览 🚀

摘要

Ant Design 作为一个昔日世界第一的 UI 库,影响力自是足够深远。而由官方推出的「开箱即用的中台前端 /设计解决方案」—— Ant Design Pro 也日趋成熟。较为遗憾的是 Ant Design Pro 官方并没有提供页面标签化展示的功能,因为当时环境的需要,我走上了这条页面标签化的不归路……

关键词:Ant Design ProUmi标签页页面标签化

绪论

从 19 年偶然发现了 Ant Design Pro (以下简称 Pro )以来,对我的技术发展有着不容忽视的影响,当然本文着重讨论我在页面标签化展示的研究与实现。刚接触 Pro 的时候自己还是一个工作中用 Java,业余学习 React 而转型前端的毕业一年的菜鸟。突然面对 Pro 这样一个庞杂的脚手架(当时的版本 Pro v2 ),而且还要做一个自己本来毫无头绪的功能时,我是拒绝的,奈何没人顶上只能自己硬着头皮搞了。

道路是崎岖的

一切的起点都要从一个不得不提的官方仓库关于此讨论甚多的 issue ——能否提供 tab 切换模式说起。感谢其中相关的仓库提供的思路。当时研究了好几个仓库的源码,主要有两个思路:

第一个思路是通过点击事件来更新标签页的渲染,对其他组件还存在一定的侵入性,实现不够优雅,更为尴尬的是不支持页面的嵌套路由渲染(后来知道了路由配置中的组件其实是 Switch 组件时,应该也能实现嵌套路由渲染)。

第二个思路就没有了对于其他组件的侵入性,只需要监听 childrenlocation 的变化即可。印象中由于彼时 hooks 还未发布,通过类组件实现颇为繁琐。hooks 正式发布后又重构成了函数式组件实现。

前途是光明的

近两年的时间里随着各方面的不断成熟,当前实现 Ant Design Pro Plus 已经支持了足够丰富的功能:

得益于 hooks 功能的加持,封装了 useTabs 的 hook,核心功能一目了然。如此,只需要根据状态渲染标签页即可。

核心逻辑

作为一个不那么简单的功能,需要注意的细节自然不少,这里重点介绍两个核心函数。

getOriginalRenderRoute

根据 location 和原始的路由定义解析出待渲染的路由定义对象 RenderRoute,**核心是算出正确的 renderKey**,标签页的唯一性主要由其决定(基于路由参数的标签页还需要结合哈希值)。

注释应该还算清晰,尽力覆盖了一些我所能考虑到的各种情况。特别的是做了一个缓存,避免反复计算 renderKey

withRouteTab

页面性能优化高阶函数。默认情况下,每次切换都会触发所有标签页的渲染,当打开标签页太多且页面较为复杂时,由于没有必要的渲染可能会造成操作标签页时有明显的反馈延迟,可通过此高阶函数包裹页面组件以优化渲染性能。

一个难题

近两年的发展并不是一帆风顺,很多问题都算是不痛不痒,一个萝卜一个坑都能解决,但是一个关于 Umi 的难题折磨了我很长的时间。

Umi 升级到 3.0 的时候也尝试升级项目的 Umi 版本,不升不知道,一升吓一跳,切换时所有标签页都会渲染成当前 location 对应的页面内容,当时我就震惊了,不禁陷入了哲学三问:我是谁?我在哪儿?我要干嘛?

相当长的一段时间都毫无头绪,也提了 issue —— 「想了解一下 umi 2 与 3 对路由组件处理的异同」,没有得到反馈 _(:3J∠)_ 直到感觉被 Umi 抛下了好远好远,无奈再次硬着头皮研究了 Umi 两个版本之间关于路由渲染的源码,功夫不负有心人,最后终于找到了病根,成功升级 Umi 的版本,这也是该功能仅支持 ^umi@2.0.0 | ^umi@3.3.8 的原因。

总结

对比已知的其他实现要么断更,要么功能不够完善,要么二者兼备。一个功能维护了近两年,之所以开篇提到「我走上了这条页面标签化的不归路」也正是这个原因,好在现在思路越来越清晰了。

正是在输出这篇文章的时候,突然想到可以将前文提到的两种思路整合,貌似也是个不错的方案,即只监听 location 并移除 children 的依赖。不过后续的重点可能还是侧重于将此功能插件化集成到 Umi 中。

前端一出道就碰到了 Pro,应该算是一大幸事了。以此为基础,对于前端开发的技术栈有了一系列较为成熟的认识,同时培养了较好的开发习惯,也为后续的自身技术上的可持续发展提供了源源不断的动力。当然,由于自身能力所限,过程中可能会有不足之处,对于 Pro 页面标签化展示这一问题重点是抛砖引玉,如果有任何意见或建议,欢迎批评指正。

2867 次点击
所在节点    程序员
16 条回复
supercaizehua
2021-05-15 21:04:55 +08:00
没写参考文献,打回去重新写
theprimone
2021-05-15 21:25:58 +08:00
@supercaizehua 本文不必参考任何文献 [doge]
aaronlam
2021-05-16 00:31:56 +08:00
感觉楼主这种死磕到底的精神挺值得学习的,刚开始转前端,我也是为了做需求一头扎进了 Antd Design Pro 里不能自拔,后面逐渐熟悉了前端那一套工程化的生态,才慢慢的上手。
Kylin30
2021-05-16 05:16:22 +08:00
现在第一 ui 库是哪个?
theprimone
2021-05-16 08:55:35 +08:00
@aaronlam 也是后端转前端吗? Pro 的成套的技术实现认真学习一下确实能让新人快速建立起 React 开发的理论基础。不过 v2 之后开始逐渐屏蔽了越来越多的编译细节。
theprimone
2021-05-16 09:00:32 +08:00
@Kylin30 应该是 Material UI,当然我是根据 star 来判断的。antd 的仓库在 3 月份被黑过一次,导致 star 全丢了,现在差不多才赶上 Material UI 的 2/3 😂
theprimone
2021-05-16 11:08:31 +08:00
啊这,这两天 antd 突然 star 起飞了,貌似重回第一了 _(:3J∠)_
jenlors
2021-05-16 14:05:01 +08:00
anguiao
2021-05-16 18:54:09 +08:00
@long2ice 之前出问题了,这个只是恢复了以前的 star 。
theprimone
2021-05-16 19:01:02 +08:00
@anguiao 我也猜测是这个原因,这两天涨得太离谱了,大佬知道哪里有恢复 star 的说明吗?
thtznet
2021-05-17 08:57:33 +08:00
d2-admin 很早就写了相当成熟的标签切换逻辑,可惜基于 vue2 的 element ui,没有持续更新到 vue3
Dragonphy
2021-05-17 09:05:38 +08:00
@thtznet d2-admin 和 d2-crud-plus 的文档写得挺靠谱,我这个 vue 都不会的撸了一套页面
theprimone
2021-05-17 09:33:26 +08:00
@thtznet 看了一下效果确实挺不错的,但是个人感觉整体风格感觉怪怪的 😂
Incineroar
2021-05-17 14:20:09 +08:00
_(:3J∠)_ 学习一下解决问题的思路,感觉比找工八股文有意思多了
theprimone
2021-05-17 14:25:58 +08:00
theprimone
2021-05-17 14:27:53 +08:00
@Incineroar 我不是那种为了找工作专门刷题的人,都是在做自己感兴趣的项目,在过程中学习。所以我面试都是随缘的 😂

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/777147

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX