❤React体系12-React路由(ReactRouter)的进阶使用

347 阅读4分钟

❤React体系11-React路由(ReactRouter)的进阶使用

1、React.lazy 优化路由

认识

我们发现加了路由以后我们的加载缓慢了很多,React.lazy可以减少我们应用的初始加载时间,提升用户体验,对于大型单页应用(SPA)或需要优化加载时间的应用特别有用

React.lazy 是 React 提供的一个动态导入组件的方法,作用是需要时才加载组件,而不是在应用初始化时就加载所有组件,从而提高应用的性能和加载速度。

React.lazy 函数接受一个函数作为参数,动态导入组件。当组件需要被渲染时,React 将调用这个函数来加载组件。加载完成后,组件将被缓存,以便在将来的渲染中重用。

React.lazy 结合 Suspense 组件使用时,可以优雅地处理动态加载组件时的 loading 状态,使代码更加清晰和易于维护。

使用lazy,优化我们的router.tsx

const Home = lazy(() => import('@/pages/Home'));
const Login = lazy(() => import('@/pages/Login'));
const NotFind = lazy(() => import('@/pages/NotFind'));

2、使用Suspense 默认加载效果

v6之前的版本使用

// App.js
import React, { Suspense, lazy } from 'react';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';

const Login = lazy(() => import('./Login'));
const Admin = lazy(() => import('./Admin'));

const App = () => {
  return (
    <Router>
      <Suspense fallback={<div>Loading...</div>}>
        <Switch>
          <Route exact path="/" component={Login} />
          <Route path="/admin" component={Admin} />
        </Switch>
      </Suspense>
    </Router>
  );
};

export default App;

v6版本对此作了一些调整

// App.js
import React, { Suspense, lazy } from 'react';
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';

const Login = lazy(() => import('./Login'));
const Admin = lazy(() => import('./Admin'));

const App = () => {
  return (
    <Router>
      <Suspense fallback={<div>Loading...</div>}>
        <Routes>
          <Route path="/" element={<Login />} />
          <Route path="/admin" element={<Admin />} />
        </Routes>
      </Suspense>
    </Router>
  );
};
export default App;

刷新页面看看我们的加载效果

image.png

3、嵌套路由 Link和 Outlet的使用

接下来我们在文章之中添加两个种类的文章类型,点击的时候跳转进入对应的界面,但是前面的Article依然不进行改变

分别是访问Article的时候进入Article, 问Article/Articletype1的时候进入Article/Articletype1, 问Article/Articletype2的时候进入Article/Articletype2,

image.png

一级页面文章 Article.js

// Article.js 
import React from 'react';
import { Link, Outlet } from 'react-router-dom';

const Article = () => {
  return (
    <div>
      <h1>Article Page</h1>
      <nav>
        <Link to="Articletype1">Article Type 1</Link>{' '}
        <Link to="Articletype2">Article Type 2</Link>
      </nav>
      <Outlet />
    </div>
  );
};

export default Article;

文章类型页面组件(二级路由)

ArticleType1.js

// ArticleType1.js
import React from 'react';

const ArticleType1 = () => {
  return <div>Article Type 1 Page</div>;
};

export default ArticleType1;

ArticleType2.js

// ArticleType2.js
import React from 'react';

const ArticleType2 = () => {
  return <div>Article Type 2 Page</div>;
};

export default ArticleType2;

设置路由

导入

//导入
const ArticleType1 = lazy(() => import('@/views/article/Articletype1'));
const ArticleType2 = lazy(() => import('@/views/article/Articletype2'));

配置

//配置
 <Route path="/Article" element={<Article />}>
  <Route path="Articletype1" element={<ArticleType1 />} />
  <Route path="Articletype2" element={<ArticleType2 />} />
</Route>

接下来我们尝试一下访问Article:

点击对应的部分已经展示:

image.png

image.png

已经成功实现!

4、Link 改成编程式路由的方式进行跳转

之前我们文章的跳转采用的是Link的方式,现在我们改写成为这种编程式路由的方式进行跳转

import { Link, Outlet,useNavigate} from 'react-router-dom';

<a href="#" onClick={(e)=>{tiao1(e)}}>Article Type 1</a>

 const tiao1=(e:any)=>{
    e.preventDefault();
    navigate('/articletype1')
 }

结果我们点击,奇怪,怎么跳转到了404 呢

其实我们正确的地址应该是 '/article/articletype1'

更改以后进行尝试:

  const tiao1=(e:any)=>{
    e.preventDefault();
    navigate('/article/articletype1')
  }
  const tiao2=(e:any)=>{
    e.preventDefault();
    navigate('/article/articletype2')
  }

更改方式成功!

5、接下来在我们的后台实现一下管理部分的二级菜单效果admin(NavLinkLink)

想要的布局效果大致如下:

image.png

  • Link: Link 用于定义导航链接,但不提供样式控制。它是一个简单的 HTML <a> 标签的封装,用于在不刷新页面的情况下进行页面跳转。

  • NavLink: NavLinkLink 的增强版,它可以为当前页面匹配的链接添加活动状态(active state),通常用于设置导航链接的样式以显示当前页面或路由的状态。你可以根据路由匹配情况添加自定义的类名或样式。

需要为导航链接添加样式以反映当前页面或路由的活动状态,那么建议使用 NavLink

只是需要简单的导航链接而不需要活动状态的样式控制,使用 Link 就可。

我们文章之中使用了Link,这里我们菜单使用 NavLink

之前我们都是这么写的:

{/* NavLink */} 
<NavLink to="/" activeClassName="active">Home</NavLink>
<NavLink to="/about" activeClassName="active">About</NavLink>

结果在v6一写直接报错: 果然,这货在v6之中更改了写法,果然一步一个坑啊

v6版本之中路由更改成了下面的写法:

let activeClassName = "underline"
<NavLink
	to="/faq"
	className={({ isActive }) =>
	  isActive ? activeClassName : undefined
	}
>
  FAQs
</NavLink>

来看看匹配时候我们的路由

image.png

6、完善一下我们的路由:

javascript
复制代码
import AntdComp from "./components/AntdComp";
import Header from "./components/Header";
import Login from "./views/Login";
import Register from "./views/Register";
import ForgetPassword from "./views/ForgetPassword";
import { ButtonConfigProviderSpace } from 'antd';
import NotFind from "./views/NotFind";
import Home from "./views/Home";
import User from "./views/subs/User";
import Role from "./views/subs/Role";
import { BrowserRouterHashRouterRoutesRouteLinkNavLinkNavigate } from "react-router-dom"
function App() {
 return (
   <ConfigProvider
     theme={{
       token: {
         // Seed Token影响范围大
         colorPrimary: '#7cb305'
      },
    }}
   >
    {/* 路由器 */}
     <BrowserRouter>
      {/* 路由映射列表 */}
       <ul>
         <li>
           <Link to="/register">注册</Link>
         </li>
         <li>
           <NavLink to="/forget">忘记密码</NavLink>
         </li>
       </ul>
       <Routes>
        {/* 路由具体路径匹配 */}
         <Route path="/" element={<Navigate to="/login"></Navigate>}></Route>
         <Route path="/login" element={<Login></Login>}></Route>
         <Route path="/home" element={<Home></Home>}>
           <Route index element={<User></User>}></Route>
           <Route path="role" element={<Role></Role>}></Route>
         </Route>
         <Route path="/register" element={<Register></Register>}></Route>
         <Route path="/forget" element={<ForgetPassword></ForgetPassword>}></Route>
         <Route path="/404" element={<NotFind></NotFind>}></Route>
         <Route path="*" element={<Navigate to="/404"></Navigate>}></Route>
       </Routes>
     </BrowserRouter>
   </ConfigProvider>
);
}
​
export default App;
​

在Home下面配置路由渲染出口

import React from 'react'
import { OutletLink } from "react-router-dom"export default function Home() {
   return (
       <div style={{ display: "flex" }}>
           <div style={{ width: "200px", backgroundColor: "pink" }}>
               <ul>
                   <li>
                       <Link to="/home/user">用户</Link>
                   </li>
                   <li>
                       <Link to="/home/role">角色</Link>
                   </li>
               </ul>
           </div>
           <div>
               <h3>content</h3>
               <Outlet></Outlet>
           </div>
       </div>
  )
}

检查一下我们的路由,完美实现!