- 作者:老汪软件技巧
- 发表时间:2024-11-27 15:07
- 浏览量:
根据配置生成路由
React路由看似只能由Route组件包裹组件的结构来构成,但是其实也可以通过编写路由数组配置然后通过数组循环来生成Route组件包裹组件的结构。
安装依赖react-router-dom,这是React中用于处理路由的库
npm install react-router-dom
创建路由配置
创建一个路由配置文件,其中定义了一个路由数组,包含各个路由的路径、组件等信息
// src/router/index.js
const routes = [
{
path: '/', // 路由路径
component: () => import('./views/Home'), // 路由对应的组件
exact: true
},
{
path: '/about',
component: () => import('./views/About'),
},
{
path: '/contact',
component: () => import('./views/Contact'),
},
// 可以添加更多的路由配置...
];
export default routes;
exact 属性用于指定路由匹配是否需要完全精确匹配路径。当 exact 设置为 true 时,只有当URL与path属性完全一致时,对应的路由组件才会被渲染。如果没有设置 exact 或者设置为 false,那么只要URL包含path指定的路径,该路由就会被认为匹配,进而渲染相应的组件。
假设有以下两个路由配置:
Home页面:路径为 /User Profile页面:路径为 /user/:id
<Routes>
<Route path="/" element={<Home />} exact />
<Route path="/user/:id" element={<UserProfile />} />
Routes>
两个路由都是使用 exact: true时:
当访问 / 时,只有 Home 组件会被渲染。当访问 /user/123 时,只有 UserProfile 组件会被渲染。
不使用 exact 或 exact: false时:
当访问 / 时,Home 组件会被渲染。当访问 /user/123 时,由于 /user/:id 包含了 /,所以 Home 和 UserProfile 两个组件都会被渲染。如果没有设置 exact,React Router 认为 / 是 /user/:id 的一部分。
通常情况下,对于首页(通常是根路径 /),需要使用 exact: true,以避免其他路径(如 /user/:id)也匹配到根路径,导致不必要的组件渲染。而对于其他具体的路径,则不需要设置 exact,因为它们通常已经足够具体,不会引起混淆。
代码中使用了import()函数来异步加载组件,这样就实现了按需加载,有助于提高应用的性能。
也可以使用lazyHook懒加载的写法,如下所示:
// src/router/index.js
import React, { lazy } from 'react'
// 懒加载路由
const Home = lazy(()=>import("./views/Home"))
const About = lazy(()=>import("./views/About"))
const routes = [
{
path: '/',
component: Home
},
{
path: '/about',
component: About
},
{
path: '/contact',
component: lazy(() => import('./views/Contact')),
},
]
export default routes
动态生成路由
在项目的主应用文件(如App.jsx)中,使用react-router-dom提供的和组件,结合上面的配置来动态生成路由。
// src/App.jsx
import React from 'react';
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import routes from './router/index.js';
function App() {
return (
<Router>
<Routes>
{routes.map((route, index) => (
<Route
key={index}
path={route.path}
element={<route.component />}
exact={route.exact}
/>
))}
Routes>
Router>
);
}
export default App;
element={},它会根据路由数组配置中数组元素的component属性来加载对应的组件。
也可以在main.jsx文件中使用包裹根组件
// src/main.jsx
import React from 'react'; // 用于创建组件的
import { createRoot } from 'react-dom/client'; // 用于渲染页面的
import { Provider } from 'react-redux';
import store from './store/index.js';
import App from './App.jsx';
import { BrowserRouter} from 'react-router-dom';
createRoot(document.getElementById('root')).render(
<Provider store={store}>
<BrowserRouter>
<App />
BrowserRouter>
Provider>
)
使用lazyHook懒加载路由组件时,需要在App.js中,为所有懒加载的组件提供了一个错误边界或加载状态
// src/App.jsx
import React, { Suspense } from 'react';
import { Routes, Route } from 'react-router-dom';
import routes from './router/index.js';
function App() {
return (
<Suspense fallback={<div>Loading...div>}>
<Routes>
{routes.map((route, index) => (
<Route
key={index}
path={route.path}
element={<route.component />}
exact={route.exact}
/>
))}
Routes>
Suspense>
);
}
export default App;
还可以将配置的路由数组循环动态生成路由的代码抽离成一个单独的函数
// src/router/createRoute.js
import React from 'react';
import { Route } from 'react-router-dom';
// 接受一个路由数组
const createRoute = (routes) => {
return routes.map((route,index) => {
return (
<Route
key={index}
path={route.path}
element={<route.component />}
exact={route.exact}
/>
)
})
}
export default createRoute;
// src/App.jsx
import React, { Suspense } from 'react';
import { Routes, Route } from 'react-router-dom';
import routes from './router/index.js';
import createRoute from './router/createRoute.js'
function App() {
return (
<Suspense fallback={<div>Loading...div>}>
<Routes>
{
createRoute(routes)
}
Routes>
Suspense>
);
}
export default App;
配置路由中包含子路由
目录结构:
创建一个路由配置文件,其中定义了各个路由及其子路由的信息,使用懒加载来优化性能
// src/router/index.js
import React from 'react';
const routes = [
{
path: '/',
component: React.lazy(() => import('./views/Home')),
exact: true,
},
{
path: '/dashboard',
component: React.lazy(() => import('./views/Dashboard')),
children: [
{
path: 'users',
component: React.lazy(() => import('./views/Users')),
},
{
path: 'settings',
component: React.lazy(() => import('./views/Settings')),
},
],
},
{
path: '/about',
component: React.lazy(() => import('./views/About')),
},
{
path: '/contact',
component: React.lazy(() => import('./views/Contact')),
},
];
export default routes;
动态生成路由的方法,为了处理懒加载组件的加载状态,需要添加组件
// src/router/createRoute.js
import React from 'react';
import { Route } from 'react-router-dom';
import { Suspense } from 'react'
const renderRoutes = (routes) => {
return routes.map((route, index) => {
// 当前路由配置项 route 包含 children 属性,递归调用 renderRoutes 函数来处理子路由
if (route.children) {
return (
<Route
key={index}
path={route.path}
element={
<Suspense>
<route.component />
Suspense>
}
exact={route.exact}
>
{renderRoutes(route.children)}
Route>
);
}
return (
<Route
key={index}
path={route.path}
element={<route.component />}
exact={route.exact}
/>
);
});
};
export default renderRoutes;
// src/main.jsx
import React from 'react'; // 用于创建组件的
import { createRoot } from 'react-dom/client'; // 用于渲染页面的
import { Provider } from 'react-redux';
import store from './store/index.js';
import App from './App.jsx';
import { BrowserRouter} from 'react-router-dom';
createRoot(document.getElementById('root')).render(
<Provider store={store}>
<BrowserRouter>
<App />
BrowserRouter>
Provider>
)
// src/App.jsx
import React, { Suspense } from 'react';
import { Routes, Route } from 'react-router-dom';
import routes from './router/index.js';
import renderRoutes from './router/createRoute.js'
function App() {
return (
<Suspense>
<Routes>
{
renderRoutes(routes)
}
Routes>
Suspense>
);
}
export default App;
为了在父组件中正确显示子路由的内容,需要在父组件中使用组件。组件用于渲染嵌套的子路由。
// src/views/Dashboard/index.jsx
import { Outlet,Link } from 'react-router-dom'
import React from 'react';
const Dashboard = () => {
return (
<>
<h1>Dashboard 页面h1>
<nav>
<ul>
<li><Link to="/dashboard/users">UsersLink>li>
<li><Link to="/dashboard/settings">SettingsLink>li>
ul>
nav>
<Outlet />
>
)
}
export default Dashboard;