react-router
组件创建路由表路由模式创建路由表映射组件RouterProvider路由跳转Link组件NavLink组件嵌套视图Outlet组件布局路由404Route组件Index路由路由懒加载(lazy)loadercaseSensitiveerrorElement/ErrorBoundaryHook路径参数和查询字符串参考
组件
创建路由表
路由模式
react-router提供三种路由模式:
createBrowserRouter
: 基于History API
createMemoryRouter
: 在内存中维护一个自己的历史记录堆栈
createHashRouter
基于Hash API
创建路由表
以
createBrowserRouter
为例:用数组的形式创建路由表:
const router = createBrowserRouter([ { path: "/", element: <Root />, children: [ { path: "dashboard", element: <Dashboard />, }, { path: "about", element: <About />, }, ], }, ]);
以组件的形式创建路由表:
const router = createBrowserRouter( createRoutesFromElements( <Route> <Route path="/" element={<Layout />}> <Route path="/" element={<Navigate to={"/home"}></Navigate>} /> <Route path="home" element={<Home />}></Route> </Route> <Route path="404" element={<Page404 />}></Route> <Route path="*" element={<Navigate to="/404" replace />} /> </Route> ) );
映射组件
无论是以数组还是组件的形式创建路由表,都需要传递两个参数:
- path: 匹配的路由
- element: 映射的组件
react-router通过这两个参数将组件映射到对应的路由上,当访问到匹配的路由时,就会显示对应的组
<Route path="home" element={<Home />}></Route>
RouterProvider
RouterProvider
是React Router提供的一个组件,它可以将你创建的router应用到你的项目中。它有一个属性router
,你可以将createBrowserRouter
或其他方式创建router
的函数返回的值赋给它。例如:ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render( <React.StrictMode> <RouterProvider router={router}></RouterProvider> </React.StrictMode>, )
RouterProvider还有一个可选属性
fallbackElement
,它可以让你在路由加载过程中显示一个自定义的组件,例如一个加载动画。路由跳转
Link组件
通过
Link
件进行跳转<nav> <Link to="/invoices">Invoices</Link> <Link to="/expenses">Expenses</Link> </nav>
Link组件需要传递参数
to
,表示要跳转的路径。NavLink组件
除了Link组件外,还可以通过
NavLink
组件来进行跳转。NavLink
与Link
的区别是:NavLink
是有状态的,它可以判断to
匹配的路径是否是当前路径,可以由此来做一些样式处理,这在做导航栏的时候很有用。<p> <NavLink to="/a" className={({ isActive }) => isActive ? "red" : "blue"}>A</NavLink> <NavLink to="/b" className={({ isActive }) => isActive ? "red" : "blue"}>B</NavLink> </p>
嵌套视图
Outlet组件
将子路由嵌套父路由中。
<Route path="/" element={<App />}> <Route path="home" element={<Home />}></Route> </Route>
父路由组件还应该引入
Outlet
组件,这样嵌套的子组件就会在<Outlet />
组件的位置上渲染。function App() { return ( <div className="App"> <Nav /> <Outlet /> </div> ); }
布局路由
如果一个Route组件只有element属性,而没有path属性,那么这个路由将会变为布局路由。
<Route element={element={ <div> <h1>Layout</h1> <Outlet /> </div> }}> <Route path="home" element={<Home />}></Route> </Route>
404
实现404的思路很简单,首先需要创建一个404页面的路由,接下来实现一个重定向,这需要用到Navigate
<Route path="404" element={<Page404 />}></Route> <Route path="*" element={<Navigate to="/404" replace />} />
Route组件
Index路由
Index路由可以认为是父路由的默认路由,当父路由匹配,子路由都不匹配的时候,使用Index路由。
<Route path="/a" element={<A />}> <Route index element={<h2>1</h2>} /> <Route path=":id" element={<Child /> } /> </Route>
- /a 匹配index路由
- /a/1 匹配
<Child />
如果没有index路由,当出现父路由匹配,子路由都不匹配的情况时,就会只使用父路由组件,如果此时父路由没有组件(
element
参数),则不会匹配到任何组件。路由懒加载(lazy)
有时候出于bundle体积考虑,需要将路由组件拆分成单独的bundle文件,实现按需加载,这个时候就需要使用lazy。
<Route path="tabs" lazy={()=>import('./page/TabList/tabList')}></Route>
需要注意的是,此时tabList文件中组件必须导出一个名称为
Component
的组件。可以更改displayName
属性来改变展示的组件名。// ✔ export function Component() { return ( <> <h1>You made it!</h1> <p>{"data"}</p> </> ); } // 更改在react-devtool中的名称 Component.displayName = "TodoList"; // ✖ export default function Component() { return ( <> <h1>You made it!</h1> <p>{'data'}</p> </> ); }
loader
路由加载器在路由呈现之前调用,要使用它需要传递一个函数,它的返回值将会被传入路由组件中,通过
useLoaderData
为元素提供数据。加载器函数有两个重要的参数:
request
和params
,前者是对应用程序发出的请求实例,后者是解析后的路由参数。function handleLoader({request, params}: any) { const url = new URL(request.url) console.log(url) console.log(params) return "123"; } <Route path="tabs" loader={handleLoader} lazy={() => import("./page/TabList/tabList")} ></Route>
之后在路由组件中就可以利用
useLoaderData
hook来获取加载器函数的返回值了,在这个示例中是123.export function Component() { const loaderData = useLoaderData() console.log('loaderData',loaderData) return ( <> <h1>You made it!</h1> <p>{"data"}</p> </> ); }
caseSensitive
指定匹配path是否区分大小写。为true时区分大小写,否则不区分。
<Route caseSensitive path="/wEll-aCtuA11y" />
errorElement/ErrorBoundary
如果路由组件的子孙路由组件渲染出错,则默认会展示错误堆栈,如果需要自定义展示组件,则可以指定
errorElement
/ErrorBoundary
属性。建议至少在根路由组件上设置一个errorElement,特别是生存环境,避免错误堆栈被公开。
如果你想自己创建 React 元素,则使用
errorElement
,否则使用ErrorBoundary
, React Router 将会自动创建 React 元素。<Route path="/" element={<App />} ErrorBoundary={ErrorPage} /> <Route path="/" element={<App />} errorElement={<ErrorPage />} />
可以在错误页面中调用
useRouteError
来获取错误信息,返回值是一个Error对象。function ErrorPage() { const error = useRouteError() as Error console.log(error) return ( <div role="alert"> Error <pre> <code>{ error.message}</code> </pre> </div> ); }
Hook
路径参数和查询字符串
为路由添加路径参数和查询参数。
<p> <Link to="/a/1">A</Link> <Link to="/b?user=123&password=321">B</Link> </p>
使用路径参数需要配置路径参数名称。
<Routes> <Route path="/" element={<App />} /> <Route path="/a/:id" element={<A />} /> <Route path="/b" element={<B />} /> </Routes>
读取params
import {useParams} from "react-router-dom" export default function A(){ const params = useParams() console.log(params); return <div>A</div> }
读取searchParams
import {useSearchParams} from "react-router-dom" export default function B(){ const [searchParams,setSearchParams] = useSearchParams() console.log(searchParams.toString()); return <div>B</div> }