美文网首页
react-router-dom v6 基本使用

react-router-dom v6 基本使用

作者: 麦西的西 | 来源:发表于2022-08-24 22:13 被阅读0次

    一、安装

    npm install react-router-dom@6 -S
    

    二、使用

    我们使用vite初始化react项目:

    yarn create vite react-router-v6-demo --template react
    

    更多关于vite的使用,参考vite官网

    1. 基本的路由配置

    // main.jsx 入口文件
    import React from 'react';
    import ReactDOM from 'react-dom/client';
    import App from './App';
    import './index.css';
    
    ReactDOM.createRoot(document.getElementById('root')).render(
      <React.StrictMode>
        <App />
      </React.StrictMode>
    );
    
    // App.jsx
    import React from 'react';
    import './App.css';
    
    import { BrowserRouter, Routes, Route } from 'react-router-dom';
    
    import BasicLayout from './layout/BasicLayout';
    import Home from './pages/Home';
    import ArticleList from './pages/ArticleList';
    import Detail from './pages/Detail';
    
    const App = () => {
      return (
        <BrowserRouter>
          <Routes>
            <Route path='/' element={<BasicLayout />}>
              <Route index element={<Home />} />
              <Route path='articleList' element={<ArticleList />} />
              <Route path='articleList/:id' element={<Detail />} />
              <Route path='*' element={<NotFound />} />
            </Route>
          </Routes>
        </BrowserRouter>
      );
    }
    
    export default App;
    

    最外层的Route里面包含了四条路由(嵌套路由,后面会详细说明),其中:
    index 表示是索引路由。当地址为'/'的时候,默认打开 Home 页面。
    path='articleList/:id'是路由传参,比较适用于列表详情的场景,通过不同的id展示不同的文章。
    path='\*'表示可以匹配任何路由,当找不到路由时候,会默认跳到 NotFound 页面。

    2. 嵌套路由

    在Route中包含子路由即可,如下:

    // ...
    <Route path='/' element={<BasicLayout />}>
      <Route index element={<Home />} />
      <Route path='articleList' element={<ArticleList />} />
      <Route path='articleList/:id' element={<Detail />} />
      <Route path='*' element={<NotFound />} />
    </Route>
    // ..
    
    // BasicLayout/index.jsx
    import React from 'react';
    import styles from './index.module.scss';
    
    import { Link, Outlet } from 'react-router-dom';
    
    const BasicLayout = () => {
      return (
        <div className={styles.basicLayout}>
          <div className={styles.nav}>
            <Link to='/'>Home</Link> | <Link to='articleList'>ArticleList</Link>
          </div>
          {/* Outlet相当于是子路由的占位符 */}
          <Outlet />
        </div>
      );
    };
    export default BasicLayout;
    

    需要注意的是 BasicLayout 里面的 <Outlet />,相当于是子路由的占位符,不可缺少。

    3.路由传参

    有两种形式传参。第一种直接使用路由传参,第二种通过query的形式传参(也就是url后加?xx=xx)的形式。
    直接路由传参的话,需要配置路由,如下:

    <Route path='articleList/:id' element={<Detail />} />
    

    跳转前的页面参数传值:

    // ArticleList/index.jsx
    import React from 'react';
    import styles from './index.module.scss';
    
    import { useNavigate } from 'react-router-dom';
    
    const ArticleList = () => {
      const navigate = useNavigate();
      return (
        <div className={styles.articleList}>
          这里是articleList页面
          <ul>
            <li onClick={() => navigate('/articleList/1?author=jack&age=18')}>文章1</li>
            <li onClick={() => navigate('/articleList/2')}>文章2</li>
            <li onClick={() => navigate('/articleList/3')}>文章3</li>
          </ul>
        </div>
      );
    };
    

    最后,在详情页面接收我们的传参:

    // Detail/index.jsx
    import React from 'react';
    import styles from './index.module.scss';
    
    import { useParams } from 'react-router-dom';
    
    const Detail = () => {
      const params = useParams();
      const [searchParams] = useSearchParams();
      console.log('searchParams', searchParams.getAll('author')[0]); // jack
      return <div className={styles.detail}>{`这里是文章${params.id}`}</div>;
    };
    
    export default Detail;
    

    我们通过useNavigate来进行跳转页面,useParams 或者 useSearchParams 来接收不同形式的传参。

    4. 路由监听

    import React, { useEffect } from 'react';
    import styles from './index.module.scss';
    
    import { useLocation } from 'react-router-dom';
    
    const NotFound = () => {
      const location = useLocation();
    
      useEffect(() => {
        console.log(location.pathname, "enter")
        return () => {
          console.log(location.pathname, "leave")
        }
      }, [location.pathname])
    
      return <div className={styles.notFound}>404</div>;
    };
    
    export default NotFound;
    

    我们可以使用 useLocation 来获取我们的当前路由的信息,然后通过 useEffect 来监听,从而实现路由监听。

    5.路由对象

    日常开发中,一般会把路由分开,单独写一个配置文件。
    react-router-dom v6 提供了路由对象的支持,我们可以把路由写成一个对象,然后通过 useRoutes 来解析。

    // config/router.config.jsx
    import React from 'react';
    import BasicLayout from '../src/layout/BasicLayout';
    import Home from '../src/pages/Home';
    import ArticleList from '../src/pages/ArticleList';
    import Detail from '../src/pages/Detail';
    import NotFound from '../src/pages/NotFound';
    
    const routes = [
      {
        path: '/',
        element: <BasicLayout />,
        children: [
          {
            index: true,
            element: <Home />
          },
          {
            path: 'articleList',
            element: <ArticleList />
          },
          {
            path: 'articleList/:id',
            element: <Detail />
          },
          {
            path: '*',
            element: <NotFound />
          }
        ]
      }
    ];
    
    export default routes;
    
    // App.jsx
    import React from 'react';
    import './App.css';
    
    import { useRoutes } from 'react-router-dom';
    import routes from '../config/router.config'
    
    const App = () => <>{useRoutes(routes)}</>
    
    export default App;
    
    // main.jsx
    import React from 'react';
    import ReactDOM from 'react-dom/client';
    import App from './App';
    import './index.css';
    
    import { BrowserRouter } from 'react-router-dom';
    
    ReactDOM.createRoot(document.getElementById('root')).render(
      <React.StrictMode>
        <BrowserRouter>
          <App />
        </BrowserRouter>
      </React.StrictMode>
    );
    

    其实也可以自己手写一个 getRoutes 方法来从配置文件中解析出路由。

    App.jsx
    import React from 'react';
    import './App.css';
    
    import { useRoutes, Routes, Route } from 'react-router-dom';
    import routes from '../config/router.config';
    
    const getRoutes = (routes) => {
      const routesElement = routes.map((item, index) => {
        return (
          <Route index={item.index} path={item.path} element={item.element} key={`${item.path}${index}`}>
            {item.children?.length ? getRoutes(item.children) : null}
          </Route>
        );
      });
      return routesElement;
    };
    // const App = () => <>{useRoutes(routes)}</>
    const App = () => <Routes>{getRoutes(routes)}</Routes>
    
    export default App;
    

    6. 路由懒加载

    通过动态 import 导入,能够打包成单独的 chunk。
    再加上 react 提供的懒加载api lazySuspense即可实现路由懒加载。

    // config/router.config.jsx
    import React, { Suspense, lazy } from 'react';
    import BasicLayout from '../src/layout/BasicLayout';
    
    const lazyLoad = (src) => <Suspense fallback={<>...</>}>{React.createElement(lazy(src))}</Suspense>;
    
    const routes = [
      {
        path: '/',
        element: <BasicLayout />, // BasicLayout是基本布局,不必使用懒加载
        children: [
          {
            index: true,
            element: lazyLoad(() => import('../src/pages/Home'))
          },
          {
            path: 'articleList',
            element: lazyLoad(() => import('../src/pages/ArticleList'))
          },
          {
            path: 'articleList/:id',
            element: lazyLoad(() => import('../src/pages/Detail'))
          },
          {
            path: '*',
            element: lazyLoad(() => import('../src/pages/NotFound'))
          }
        ]
      }
    ];
    
    export default routes;```
    

    // App.jsx
    import React from 'react';
    import './App.css';

    import { useRoutes } from 'react-router-dom';
    import routes from '../config/router.config';

    const App = () => <>{useRoutes(routes)}</>;

    export default App;

    这样就实现了路由懒加载。每次打开新的路由时,就会请求该路由对应组件的资源。
    
    具体效果图:
    ![](https://img.haomeiwen.com/i1745991/1a63d5bed0958229.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    
    完整源码已上传github:
    https://github.com/RhysZhao/react-router-v6-demo
    
    **参考资料:**
    [React Router v6官方文档](https://reactrouter.com/docs/en/v6/getting-started/overview)

    相关文章

      网友评论

          本文标题:react-router-dom v6 基本使用

          本文链接:https://www.haomeiwen.com/subject/comogrtx.html