react-router-dom V5 使用指南(1)
- react-router 提供了路由核心接口,如 Router、Route、Switch 等,未提供終端操作相關的接口;
- react-router-dom 提供了瀏覽器端接口,BrowserRouter、HashRouter,Route、Link 等API;
- react-router-native 提供了 native 端的相關接口。
學習方法
初學者建議先熟悉一遍 官網文檔react-router-dom,看找一篇闡述的比較清楚的實戰文章,這里我整理了一些資料:
實用例子
路由跳轉
演示地址:https://reactrouter.com/web/example/basic
,這是一個非常簡單的例子,從這個例子可以學到在React中路由功能是如何實現的,沒有什么難度:
- Link:實現了URL點擊跳轉的功能,點擊它可以跳轉到指定的路由URL
- Route:用於配置路由
- Switch:保證在一組路由中只渲染一個
獲取 URL Params
演示地址:https://reactrouter.com/web/example/url-params
,這個例子也比較簡單沒什么值得說的:
- useParams: 可以在任意級別的組件里獲取 URL Params。V5.1之前非Route子組件是沒辦法獲取到,你需要借助 withRouter。
路由嵌套
演示地址:https://reactrouter.com/web/example/nesting
,路由嵌套理解為:在 Route 組件的子孫組件中存在 Route 組件,比如:
<Route path="/topics">
<h1>parent</h1>
<Route path="/topics/:topicId">
child
</Route>
</Route>
值得注意的是,演示地址中使用了 useRouteMatch
,它在這個例子中的作用是將與他匹配成功的路由信息找出來,舉個例子就很容易理解:
import React from "react";
import {
BrowserRouter as Router,
Switch,
Route,
Link,
useParams,
useRouteMatch
} from "react-router-dom";
export default function NestingExample() {
return (
<Router>
<Switch>
<Route path="/topics">
<Topics />
</Route>
</Switch>
</Router>
);
}
function Topics() {
let { path, url } = useRouteMatch();
console.log(useRouteMatch())
// 在這里必須使用 useRouteMatch 找出當前匹配成功的 Route 的 path 信息, 否則子路由無法跳轉
return (
<div>
<h2>Topics</h2>
<ul>
<li>
<Link to={`${url}/rendering`}>Rendering with React</Link>
</li>
</ul>
<Switch>
<Route path={`${path}/:topicId`}>
<Topic />
</Route>
</Switch>
</div>
);
}
function Topic() {
let { topicId } = useParams();
console.log(useRouteMatch())
return (
<div>
<h3>{topicId}</h3>
</div>
);
}
當訪問 url path 為 /topics/props-v-state
時,打印信息如下:
重定向
演示地址:https://reactrouter.com/web/example/auth-workflow
,重定向是路由系統中不可或缺的功能,常被用於登錄跳轉等場景中,由於React崇尚一切皆組件的思想,所以在React中,當您需要重定向時,只需返回一個 Redirect
組件:
// state 常用來攜帶額外信息
<Redirect
to={{
pathname: "/login",
state: { from: '/orders' }
}}
/>
在該演示地址代碼中(簡化后),一個非常值得學習的技巧是:ProtectedPage
是需要登錄才能訪問的,但是我們將登錄校驗以及重定向的操作封裝到了 PrivateRoute
組件中,兩者被隔離開,降低代碼邏輯的耦合行,大大增大了代碼的復用性:
export default function AuthExample() {
return (
<Router>
<div>
<Switch>
<Route path="/login">
<LoginPage />
</Route>
<PrivateRoute path="/protected">
<ProtectedPage />
</PrivateRoute>
</Switch>
</div>
</Router>
);
}
function PrivateRoute({ children, ...rest }) {
return (
<Route
{...rest}
render={({ location }) =>
fakeAuth.isAuthenticated ? (
children
) : (
<Redirect
to={{
pathname: "/login",
state: { from: location }
}}
/>
)
}
/>
);
}