一、引言
从Jquery、Extjs等JS UI库 的mvc时代过来的程序猿,多标签那会从来不是个问题。到react的csr项目发现都是清一色基于react-router单页应用,而现存的多标签解决方案都要么依赖框架加插件(umi-plugin-keep-alive)的加持,要么依赖额外的库(react-activation、react-keepalive-router等)。上框架心里接受不了,因为框架往往是基于当下技术的工程最佳实践,对于技术变化迅速的前端领域,入坑后要学不动了往往就意味着被后浪的洪流淘汰。不上框架,上额外库,又得学习一大堆看的一脸懵逼的晦涩概念。只基于react-router和原生组件来实现多标签效果,市场上没有解决方案。
笔者之前在webpack搭建的AntdFront 中,只采用路由算法也实现了多标签效果。于是心中就产生了很大的疑惑,既然react-router 可以获取到具体的组件,组件都拿到了,多标签这么困难么?
AntdFront定位是实验性的按钮级权限多标签微前端模板,自己挖的坑,还得自己填。本文就围绕该项目 2.0版基于路由的多标签微前端实践过程中的几个关键问题,谈谈自己的理解和心得体会。
二、实践过程中的几个关键问题
1.为什么要多标签
多标签首先得能状态保留才有意义,是个用户体验问题。因为多标签,用户就可以一边上传文件,一边填写表单,妈妈再也不用担心用户的某些误操作导致表单重填的问题。两功能页面间可以做到互不干扰,且对于一些临时数据不需要额外的数据持久化逻辑,解放开发者的心智大脑。
2.为什么要router
antdFront 在1.0版中,只采用路由算法实现的多标签,在实践过程中,没有正经的路由,导航新的URL就得通过一些莫名奇妙的约定函数来实现。对于开发者说,都是额外的心智负担。最终放弃该方案的理由还是嵌套路由。将url 手工对应到组件还挺好实现,但是要对应到组件里的组件,且让组件的工程学开发人性化就有点困难了。好在有了react-router6,让嵌套路由变得不在晦涩。
3.现存解决方案 keepalive的缺点
现存react的keepalive是一套缓存方案,缓存的页面是无法进行交互的。也就是解决了用户某些误操作导致表单重填,额外的数据持久化逻辑的问题。但是没有解决一边上传文件,一边填写表单的问题。
其次引入keepalive,需要额外学习一大堆概念和用法限定。react的keepalive非官方特性,往往由个人团队开发,API不稳定。造成后期升级代码维护成本增加。
4.实现多标签的关键点是什么
1、拿到经路由算法筛选后的组件。
react-router6 是 react-router与 reach-router的 合并版本,是大致借鉴了reach-router的成功实践而对react-router的重构。它非常巧妙的使用context,利用 useOutlet 接口拿到不同层级的路由嵌套组件,非常完美的解决了嵌套路由的开发体验问题。下面tabRoute.jsx核心代码为例:
import {
useState } from "react";
import {
Tabs } from "antd";
import {
useOutlet,useNavigate,useLocation,generatePath,useParams } from "react-router-dom";
import {
usePersistFn, useCreation } from "ahooks";
import memoized from "nano-memoize";
import {
i18n } from "@lingui/core";
const {
TabPane } = Tabs;
const getTabPath = (tab) => {
return generatePath(tab.location.pathname,tab.params)
}
// tab的select key = location.pathname + , + matchpath
// matchpath为 config里配置的路由路径
// 以此解决 微端情况下 tab 的 key 相同导致页面可能丢失的问题。
const generTabKey = memoized((location,matchp