文章目錄
路由和菜單是組織起一個應用的關鍵骨架,pro 中的路由爲了方便管理,使用了中心化的方式,在 config.ts
統一配置和管理。
1. 基本結構
在這一部分,腳手架通過結合一些配置文件、基本算法及工具函數,搭建好了路由和菜單的基本框架,主要涉及以下幾個模塊/功能:
路由管理
通過約定的語法根據在config.ts
中配置路由。菜單生成
根據路由配置來生成菜單。菜單項名稱,嵌套路徑與路由高度耦合。麪包屑
組件 PageHeaderWrapper 中內置的麪包屑,也可通過 RouteContext 提供的信息自定義生成。
下面簡單介紹下各個模塊的基本思路,如果你對實現過程不感興趣,只想瞭解應該怎麼實現相關需求,可以直接查看需求實例。
1.1 路由
目前腳手架中所有的路由都通過 config.ts
來統一管理,在 umi 的配置中我們增加了一些參數,如 name
,icon
,hideChildrenInMenu
,authority
,來輔助生成菜單。其中:
-
name
和icon
分別代表生成菜單項的文本和圖標。 -
hideChildrenInMenu
用於隱藏不需要在菜單中展示的子路由。用法可以查看分步表單
的配置。 -
hideInMenu
可以在菜單中不展示這個路由,包括子路由。 -
authority
用來配置這個路由的權限,如果配置了將會驗證當前用戶的權限,並決定是否展示。
你可能注意到配置中的
name
和菜單實際展示的不同,這是因爲我們使用了全球化組件的原因,具體參見 i18n
1.2 菜單
菜單根據 config.ts
生成。
如果你的項目並不需要菜單,你可以在 src/layouts/BasicLayout.tsx 中設置
menuRender={false}
。
1.3 從服務器請求菜單
你可以在 src/layouts/BasicLayout.tsx 中修改 menuDataRender
,並在代碼中發起 http 請求,只需服務器返回下面格式的 json 即可。
const [menuData, setMenuData] = useState([]);
useEffect(() => {
// 這裏是一個演示用法
// 真實項目中建議使用 dva dispatch 或者 umi-request
fetch('/api/example.json')
.then(response => response.json())
.then(data => {
setMenuData(data || []);
});
}, []);
...
return (
<ProLayout
// ...
menuDataRender={() => menuData}
// ...
/>
);
menuData
數據格式如下,ts 定義在此:MenuDataItem.
[
{
"path": "/dashboard",
"name": "dashboard",
"icon": "dashboard",
"children": [
{
"path": "/dashboard/analysis",
"name": "analysis"
},
{
"path": "/dashboard/monitor",
"name": "monitor"
},
{
"path": "/dashboard/workplace",
"name": "workplace"
}
]
}
// ....
]
注意 path 必須要在 config.ts 中定義。(約定式路由不需要,只需頁面真實有效即可)注意 如果沒有選用 typescript,config.js 中菜單的嵌套寫法,需要把 “children” 換成 “routes”
1.4 麪包屑
麪包屑由 PageHeaderWrapper
實現,Layout
將 根據 MenuData
生成的 breadcrumb
,並通過 PageHeaderWrapper
將其展現。 PageHeaderWrapper
封裝至 Ant Design 的 PageHeader,api 完全相同。
2. 需求實例
上面對這部分的實現概要進行了介紹,接下來通過實際的案例來說明具體該怎麼做。
2.1 菜單跳轉到外部地址
你可以直接將完整 url 填入 path 中,框架會自動處理。
{
path: 'https://pro.ant.design/docs/getting-started-cn',
target: '_blank', // 點擊新窗口打開
name: "文檔",
}
如果你需要自定義 menuItem
的點擊邏輯,你可以通過 menuItemRender 的來實現。
2.2 新增頁面
通過區塊新增請閱讀 Block
腳手架默認提供了兩種佈局模板:基礎佈局 - BasicLayout
以及 賬戶相關佈局 - UserLayout
:
如果你的頁面可以利用這兩種佈局,那麼只需要在路由配置中增加一條即可:
// app
{
path: '/',
component: '../layouts/BasicLayout',
routes: [
// dashboard
{ path: '/', redirect: '/dashboard/analysis' },
{ path :'/dashboard/test',component:"./Dashboard/Test"},
...
},
加好後,會默認生成相關的路由及導航。
2.3 新增佈局
在腳手架中我們通過嵌套路由來實現佈局模板。config.ts
是一個數組,其中第一級數據就是我們的佈局,如果你需要新增佈局可以再直接增加一個新的一級數據。
module.exports = [
// user
{
path: '/user',
component: '../layouts/UserLayout',
routes:[...]
},
// app
{
path: '/',
component: '../layouts/BasicLayout',
routes:[...]
},
// new
{
path: '/new',
component: '../layouts/new_page',
routes:[...]
},
]
2.4 在菜單中使用自定義圖標
由於 umi 的限制,在 config.ts
是不能直接使用 React 組件的,Pro 中暫時支持使用 ant.design
本身的 icon type
,和傳入一個 img 的 url。只需要直接在 icon 屬性上配置即可,如果是個 url,Pro 會自動處理爲一個 img
標籤。
如果你想使用 iconfont 的圖標,你可以使用 ant.design 的自定義圖標.
2.5 帶參數的路由
腳手架默認支持帶參數的路由,但是在菜單中顯示帶參數的路由並不是個好主意,我們並不會自動的幫你注入一個參數,你可能需要在代碼中自行處理。
{
path: '/dashboard/:page',
hideInMenu:true,
name: 'analysis',
component: './Dashboard/Analysis',
},
你可以通過以下代碼來跳轉到這個路由:
import router from 'umi/router';
router.push('/dashboard/anyParams');
//or
import Link from 'umi/link';
<Link to="/dashboard/anyParams">go</Link>;
在路由組件中,可以通過this.props.match.params
來獲得路由參數。更多詳細內容請參見:umi#路由