前言
??最近在做項(xiàng)目重構(gòu)的事情氢卡,原來的一個Vue項(xiàng)目有幾十個菜單秉犹,項(xiàng)目大的令人發(fā)指,所以準(zhǔn)備重構(gòu)讼庇,使用了umi+qiankun的方式,子應(yīng)用使用了vue和react兩個類型的框架近尚。
需求
??因?yàn)橛玫搅藆mi框架蠕啄,默認(rèn)的路由文件統(tǒng)一配置在config/routers下面,并且是靜態(tài)的肿男,但是因?yàn)楝F(xiàn)在是動態(tài)添加的子應(yīng)用介汹,如果使用靜態(tài)的路由文件,每次新加一個子應(yīng)用舶沛,就需要修改一次主應(yīng)用中的路由文件再發(fā)布一次嘹承,明顯感覺不合理。因此找了一個解決動態(tài)路由的方法如庭,也是官方的解決方案叹卷。配置的方式主要是在運(yùn)行時進(jìn)行,官方文件見https://umijs.org/zh-CN/docs/runtime-config
配置
- 第一步:獲取子應(yīng)用配置列表
??因?yàn)樯婕笆褂玫轿?yīng)用的配置方式坪它,所以首先是在app.ts中調(diào)用接口獲取微應(yīng)用的信息列表
// 后面需要使用
let globalApp: any[] = [];
// 獲取微應(yīng)用信息列表
export const qiankun = getApps().then((data) => {
const apps = data?.DATA.filter((i: { entry: any }) => i.entry) || [];
const tmp = apps?.map((app: any) => {
return {
...app,
// 增加一些子應(yīng)用需要用到變量
props: {
globalState: {
...initState,
},
},
};
});
globalApp = tmp;
return {
apps: tmp,
};
});
// 返回的數(shù)據(jù)結(jié)構(gòu)
const response = [
{
enrty: 'https://10.10.10.10:111',
name: 'microApp1'
},
{
enrty: 'https://10.10.10.10:222',
name: 'microApp2'
}
];
- 第二步:在app.ts中添加路由配置
??同樣還是在app.ts中骤竹,添加patchRoutes配置,這個主要功能是為了動態(tài)增加新的路由往毡,主要功能也是利用這個實(shí)現(xiàn)的蒙揣,具體代碼如下。這里的extraRoutes是提前定義好的變量开瞭,用于存儲從接口拿到的數(shù)據(jù)懒震,forEach里面的router[0]這些是根據(jù)自己的路由配置,找到具體要添加新的路由的位置嗤详,并塞進(jìn)去一個路由配置个扰。
let extraRoutes: object[] = [];
export function patchRoutes({ routes }: any) {
extraRoutes.forEach((element: any) => {
routes[0].routes[2].routes[0].routes.unshift({
name: element.name,
path: element.path,
component: dynamic({
loader: () =>
import(
/* webpackChunkName: 'layouts__MicroAppLayout' */ '@/layouts/MicroAppLayout'
),
loading: LoadingComponent,
}),
});
});
}
- 第三步:新增一個微應(yīng)用組件
??上面第二步中我們新增加一個路由的時候使用到了component字段,本來如果使用靜態(tài)路由方式的話葱色,我們可以在config/routes中可以直接添加一條靜態(tài)路由如{name: 'microApp3', path: '/microApp3', microApp: 'microApp3'}
這樣子递宅,但是使用動態(tài)方式時卻不能直接push這么一條,會不生效,所以需要使用component的方式办龄,因此這里使用了<MicroApp></MicroApp>
的方式添加的烘绽。
??我們在layouts文件夾下面新建一個文件名稱叫MicroAppLayout.tsx
,內(nèi)容如下土榴,相當(dāng)于把它封裝成了一個組件诀姚,并通過dynamic動態(tài)引入,name也會通過props自動傳入玷禽,這樣我們會在第二步中循環(huán)獲取到的子應(yīng)用列表將element.name傳入進(jìn)去即可赫段。
import React from 'react';
import { MicroApp } from 'umi';
const MicroAppLayout: React.FC = (props: any) => {
return (
<>
<MicroApp name={props?.route?.name} />
</>
);
};
export default MicroAppLayout;
- 第四步:渲染新的路由
??通過以上的方式,我們就已經(jīng)動態(tài)的將路由配置進(jìn)行了更新矢赁,并且適配了微應(yīng)用糯笙,接下來只需要重新render一下就好了,在app.ts中添加如下代碼撩银,globalApp就是上面通過接口獲取到的微應(yīng)用列表给涕,map之后賦值給extraRoutes,再通過oldRender重新渲染即可额获。
export function render(oldRender: () => void) {
extraRoutes = globalApp?.map((app: any) => {
return {
name: app.name,
path: '/' + app.name,
};
});
oldRender();
}
總結(jié)
??通過以上的方式够庙,我們就能根據(jù)后端的返回接口,動態(tài)的添加路由了抄邀,本地的路由配置文件只需要配置一些主應(yīng)用常用的并且?guī)缀醪粫兓穆酚杉纯稍耪!.?dāng)然不光是微應(yīng)用可以使用這種方式,如果有需要的話普通的路由也可以使用這種方式進(jìn)行配置境肾,這也就省去了我們每次新加一個菜單就要更新一遍routers文件的問題剔难。