前端路由設置一般分爲 2 類:html
這也是早些時候用得最多的方式,好比:前端
{
"routes": [
{"path": "/", "component": "./a"},
{"path": "/list", "component": "./b", "Routes": ["./routes/PrivateRoute.js"]},
{
"path": "/users",
"component": "./users/_layout",
"routes": [
{"path": "/users/detail", "component": "./users/detail"},
{"path": "/users/:id", "component": "./users/id"}
]
}
]
}
複製代碼
甚至有的框架把路由和請求數據
融合到一塊兒,好比:react
const Routes = [
{
path: '/',
exact: true,
component: Home,
},
{
path: '/posts',
component: Posts,
loadData: () => loadData('posts'),
},
{
path: '/todos',
component: Todos,
loadData: () => loadData('todos'),
},
{
component: NotFound,
},
];
複製代碼
上面都是比較簡單的例子,在真實項目中路由每每還和業務邏輯息息相關,獲取數據還有前置依賴和衝突
,再考慮到路由權限、邏輯重用、模塊化、路由守護、條件判斷等等,讓集中配置式路由不堪重負,到後面寫出來到配置文件誰都看不明白了。json
典型到案例就是 react-router,它將路由邏輯分散在各個組件中變成一種特殊的路由組件
,組件在生命週期中一邊運行一邊動態生成路由規則。例如:redux
<Switch>
<Route exact path="/admin/home" component="{AdminHome}" />
<Route exact path="/admin/role/:listView" component="{AdminRole}" />
<Route path="/admin/member/:listView" component="{AdminMember}" />
</Switch>
複製代碼
這樣一來路由及業務邏輯被分散在各個相關組件中,有效的分解了集中配置式的複雜度,看上去很優雅,但也有很多新問題:小程序
既然集中配置式
和動態組件式
路由各有優點和劣勢,那有沒有更好等辦法來融合 2 者呢?其實它們的最大的問題都在於路由承擔了過多的職能(路由、取數據、業務邏輯、權限、守護、組件生命週期...)瀏覽器
迴歸到路由的本質:bash
從內部來看:路由只不過就是應用提供一種方法,用來保存記錄應用的某個視角切片。 對於沒有配置路由的單頁應用來講,整個應用就只有一個切片,路由規則定義得越多越細,系統可展現的內部切片也越多越細。因此路由就是一種記錄應用狀態的狀態。服務器
從外界來看:路由只不過就是應用提供一種方法,讓外界(用戶)能夠申請訪問哪些視圖。 那麼從這個角度說,路由無非就是攜帶了 2 個信息:react-router
咱們在路由中提取出這 2 筆信息後,直接將它們注入到咱們的狀態管理,至此路由的職能也就算完成了,接下來的事情就是狀態管理的事情,與路由無關了。
好比對於一個URL:
/admin/role/list?q={adminRole: {title: "medux", page: 1, pageSize: 20}}#q={adminRole: {_random: 34532324}}
複製代碼
咱們能夠從中間提取到這樣到信息,並將它注入redux中:
{
"views": {
"app": {"Main": true},
"adminLayout": {"Main": true},
"adminRole": {"List": true}
},
"paths": ["app.Main", "adminLayout.Main", "adminRole.List"],
"params": {
"app": {},
"adminLayout": {},
"adminRole": {
"listView": "list",
"title": "medux",
"page": 1,
"pageSize": 20,
"sortBy": "createTime",
"_random": 34532324
}
}
}
複製代碼
將路由當成是一種跟 Redux 同樣記錄着應用的狀態。只不過 Redux 是記錄在內存中由用戶經過界面交互觸發維護,而 Route 是記錄在瀏覽器地址欄中,由用戶手工輸入維護,它們本質都是同樣的。
因此在將路由轉換爲狀態以後就沒有路由什麼事了,在組件中你直接用狀態控制視圖的顯示便可:
<Switch>
{routeViews.adminHome?.Main && <AdminHome />}
{routeViews.adminRole?.List && <AdminRole />}
{routeViews.adminMember?.List && <AdminMember />}
</Switch>
複製代碼
通過以上對路由職能的單一化,路由邏輯變成很薄的一層,那咱們還須要 react-router 嗎?還須要路由組件嗎?還要啥自行車?沒那麼複雜的心智負擔了,迴歸到簡單的 MVVM 便可,用個抽象的公式來表示:
最後問題又來了,雖然路由職能變得單一,但仍是要履行職能啊,怎麼將路由變成爲狀態呢?也就是怎麼從一串 URL 字符中提取到前面所說的:展現哪些視圖
和傳遞哪些參數
,這 2 筆信息呢?
這個你固然能夠本身去設計你的路由方案,我也設計了一種:@medux/route-plan-a,能夠看看個人開源框架:Medux
以上僅表明我的探索,歡迎拍磚交流