找回密码
 会员注册
查看: 25|回复: 0

Umi4.0多页签设计

[复制链接]

2

主题

0

回帖

7

积分

新手上路

积分
7
发表于 2024-9-19 18:04:20 | 显示全部楼层 |阅读模式
在平常的后台系统开发中,常常需要缓存一些之前打开的页面,方便操作,多页签就是用来管理页面的,如下图Umi4.0版本发布到现在已经有一段时间,全新的框架当然需要学习一下新的特性和功能,由于Umi4.0使用了react-router6,所以路由有较大改动,多页签设计也需要重新调整。文章分为三部分设计思路遇到的问题扩展到自建路由一、设计思路之所以要设计多页签,是因为现有的框架路由只能单开,Vue里面即使有keep-alive,当面对类似/detail:id这种路由时也只能同时存在一个。多页签结构如下:路由与组件一对一,组件与实例一对多,实例与页签一对一以组件实例为维度构建页签,因此需劫持渲染。多页签之所以能劫持渲染是因为其就是一个高阶组件,监听路由变化生成对应的实例。自己维护当前展示的组件列表,从框架提供的全局路由信息生成对应的组件实例,向下渲染。从路由配置里面表现为所有的组件路由都是多页签路由的子路由。{  path: '/',  //多页签对应的组件  component: '@/layouts/MultiTagRoute.jsx',  flatMenu: true,  routes:[    //以下是实际路由    {      name: '组件1',      path: '/one',      component: './one',      icon: 'cluster',    },    {      name: '组件2',      path: '/two',      component: './two',      icon: 'cluster',    },  ]}那么具体的代码思路如下从框架提供的路由信息里面拿到生成组件实例的方法,维护一个页签队列监听路由变化,路由不在队列就加入,已经存在就激活,缓存使用display:'none',因为这里是显示的高阶组件式缓存,可操作性比较高。不是类似keepalive那种缓存内置。拿到对应的路由信息生成组件实例,向下渲染二、遇到的问题react-router6使用渲染路由,同时还提供了useOutLet这个hooks获取当前渲染信息。useOutLet这个hook返回的outlet比较有意思,它不是传统意义上的类似children的dom结构。「使用isValidElement检测为true,但是使用cloneElement向其传递props却不会生效」。因此想要传递props,只能按照的方式进行参数传递。此外umi框架在prolayout里面已经使用了,因此这里只能使用{outlet}这种方式渲染。umi还有有一个useAppData方法,可以返回组件实例declare function useAppData(): {  routes: Record;  routeComponents: Record>;  clientRoutes: ClientRoute[];  pluginManager: any;  rootElement: string;  basename: string;  clientLoaderData: { [routeKey: string]: any };  preloadRoute: (to: string) => void;};routeComponents里面包含了每一个组件的工厂函数,可以直接使用进行渲染。这种方式使用props就可以传递参数,可以根据实际情况选择。监听路由变化使用useLocation,在多页签里面使用useEffect监听location,此外location也能携带一些参数,用于丰富多页签的功能,例如刷新当前页签、跳转前关闭当前页签,跳转后自动刷新等功能,只要在query参数里面约定好即可。三、扩展到自建路由有了上面的设计思路,平时开发中也会遇到自建路由的需求。路由本质就是路径字符串到组件的映射。我们自建路由的配置也应如下{  name: '多页签',  component: React.lazy(() => import('./multiTag')),  path: '/',  children: [    {      name: '组件A',      path: '/componentA',      component: React.lazy(() => import('./componentA')),    },    {      name: '组件B',      path: '/componentB',      component: React.lazy(() => import('./componentB')),    }  ]}使用context维护全局字符串路径,向下传递自建跳转方法就可以模拟路由跳转,自建的路径信息数据结构与location保持一致就可以。这里还有一点需要注意的地方,传统异步加载是这样的方式()=>import('./componentA'),没有添加React.lazy,这样加载出来的文件会被解析为module。图片它不是一个react组件,如果使用了hooks在某些情况会出现rendermorethanonehooks的报错,使用时需要注意。四、总结以上就是多页签的总体设计思路,大家有什么想法,欢迎在评论区交流。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 会员注册

本版积分规则

QQ|手机版|心飞设计-版权所有:微度网络信息技术服务中心 ( 鲁ICP备17032091号-12 )|网站地图

GMT+8, 2024-12-26 11:57 , Processed in 0.367389 second(s), 25 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表