React18+Router6路由搭建(1)

一、Router6相关概念与基础

1.安装react路由所需要的组件,react-domreact-router-dom
js 复制代码
yarn add react-dom react-router-dom
  • react-dom 是 React 的官方 DOM 渲染器,用于将React组件渲染到浏览器中的DOM元素上。它提供了用于操作DOM的方法,并负责处理React组件的生命周期和更新机制。你可以使用 react-dom 来在网页中渲染和更新React应用。
  • react-router-dom 是用于在 React 应用中处理路由的库。它基于 react-router,提供了一系列用于定义和管理路由的组件和钩子函数。通过使用 react-router-dom,你可以轻松地创建多个路由、导航链接以及在不同路径下渲染不同的组件。

总结起来,react-dom 负责将 React 组件渲染到 DOM 元素上,而 react-router-dom 则专注于处理 React 应用中的路由功能。这两个库在开发 React 应用时经常被同时使用。

其中包含BrowserRouter、NavLink, Route, Routes等常用属性

  1. BrowserRouter: HTML5 History API 来管理应用程序的路由。它是 react-router 库中的 Router 组件的一种实现,用于提供路由功能并确保应用程序中的地址与当前路由状态同步。
  2. NavLink: 用于创建导航链接。它是 Link 组件的特殊版本,允许你在当前页面的 URL 与给定的链接匹配时为链接应用额外的样式或类名。
  3. Route: 用于定义应用程序中的路由和相应的组件。它匹配当前的 URL,并渲染与之匹配的组件。你可以使用 path 属性来指定要匹配的 URL 路径,然后使用 element 属性来指定与之匹配时要渲染的组件。
  4. Routes: 用于将多个 Route 组件包裹在一起,从而定义应用程序的路由层次结构。你可以在 Routes 组件中定义多个嵌套的 Route 组件,每个 Route 组件定义一个特定的路径和相应的组件。
  5. createRoot: 创建一个根 ReactDOM 渲染容器。与常规的 ReactDOM.render 方法不同,可以用于启用 React 的异步渲染模式(Concurrent Mode),从而提高应用程序的渲染性能和交互体验。
2.了解路由的工作模式

react-router6包含两种路由:BrowserRouterHashRouter

  • HashRouter:使用 URL 的哈希值实现(http://localhost:3000/#/first
    • 原理:监听 window 的 hashchange 事件来实现的
  • (推荐)BrowserRouter:使用 H5 的 history API 实现(http://localhost:3000/first
    • 原理:监听 window 的 popstate 事件来实现的
js 复制代码
import { BrowserRouter } from "react-router-dom";
const App = () => (
  <BrowserRouter>
    路由映射
  </BrowserRouter>
);
export default App;
3.配置映射关系

选定了路由模式,引入了包裹容器,接下来就是匹配url路径与页面展示组件的关系。router6中提供了 Route 组件,专门用来帮助我们进行配置路由关系。Route属性如下所示:

  • path属性:用于设置匹配到的路径;
  • element属性:设置匹配到路径后要渲染的组件;(在Router5里是使用component属性)
js 复制代码
import React from "react";
import { Route, Routes } from "react-router-dom";
import About from "./components/About";
import Demo from "./components/Demo";

export default function App(){
  return(
        {/* 路由组件 */}
        <div className="row">
          <Routes>
            <Route exact path="/" element={<About />} />
            <Route exact path="/about" element={<About />} />
            <Route path='/demo' element={<Demo />} />
          </Routes>
        </div>
  );
}

其中exact属性是为了保证/与第一个路由的 path 属性是精确匹配的,确保与 URL 的根路径匹配。 以上其实就可以在地址栏通过更换路径地址测试路由配置关系了,但这显然不符合实际的使用习惯。

二、实际案例

1.路由的执行过程
  1. 点击 Link 组件(a标签),修改了浏览器地址栏中的 url
  2. React 路由监听到地址栏 url 的变化 hashChange/popState
  3. React 路由内部遍历所有 Route 组件,使用路由规则(path)与 pathname进行匹配
  4. 当路由规则(path)能够匹配地址栏中的 pathname时,就展示该 Route 组件的内容

其中LinkNavLink都是router6提供的路由跳转方式,后者相当于前者的加强版,日常使用NavLink就可以。

Link

  • to属性:用来设置跳转到哪个路径,相当于是push操作;
  • replace属性:和to类似,也会跳转到目标路径,但其执行的是replace操作;
  • Link组件无法实现导航的高亮效果

NavLink

  • to属性,用于指定地址,会渲染成a标签的href属性
  • activeClass: 用于指定高亮的类名,默认active
  • exact: 精确匹配,表示必须精确匹配类名才生效
2.登陆权限控制

目标:对于Home页面只有在登录状态下才能访问,如果没有登录则重定向到登录页中。

方法:针对于这些权限控制免不了要引入高阶函数或者高阶组件来帮助进行一层拦截:在跳转页面时不要直接进行render目标组件,而是做一层判断-->如果有访问权限就直接render;如果没有访问权限就使用Navigate重定向组件。

过程:

编写渲染文件index.js

这里采用了自 React 18 新引入的 Concurrent Mode 渲染器。createRoot 方法返回一个根渲染器对象,它支持并发渲染。在 Concurrent Mode 下,React 可以以更高效的方式处理组件的渲染和更新,并提供更好的用户体验。

在这种写法中使用 createRoot 方法创建根渲染器,并通过 root.render() 方法渲染应用。

js 复制代码
// src/index.js
import React from "react";
import App from "./App";
import { createRoot } from "react-dom/client";
import { BrowserRouter } from "react-router-dom";

const container = document.getElementById("root");
const root = createRoot(container);
root.render(
  <BrowserRouter>
    <App />
  </BrowserRouter>
);

编写权限控制文件AuthComp.jsx

js 复制代码
import React from "react";
import { Navigate } from "react-router-dom";

// 这里的isLogin就是用来标识是否登录,实际项目一般是取redux里面的相关值
const isLogin = false;

const AuthComp = (props) => {
  const { comp:Comp } = props;

	// 如果登录就放行
  if (isLogin) return Comp;

	// 如果没有登录就重定向到Login登录页
  return <Navigate to="/login" replace/>;
};

export default AuthComp;

编写App.jsx(页面)

js 复制代码
import React from "react";
import { NavLink, Route, Routes } from "react-router-dom";
import Login from "./components/Login";
import Home from "./components/Home";
import NotFound from "./components/NotFound";

export default function App(){
  return(
    <div>
      <div className="row">
        {/*路由链接 */}
        <NavLink  to='/login'>Login</NavLink>
        <NavLink  to='/home'>Home</NavLink>
        <NavLink  to='/notFound'>NotFound</NavLink>
      </div>
      <div>
        {/* 路由组件 */}
        <div className="row">
          <Routes>
            <Route exact path="/" element={<AuthComp comp={<Home />} />} />
            <Route path='/login' element={<Login />} />
            <Route path='*' element={<NotFound />} />
          </Routes>
        </div>
      </div>
    </div>
  );
}

编写Home.jsx/Login.jsx(页面1、2)

js 复制代码
import React from 'react'
export default function Home() {
  return (
    <div>Home</div>
  )
}

至此就完成了对Home也得登录权限控制。在实际开发中判断当前是否有权限的值一般都是在redux等状态管理库中存放的,到时候根据业务需要更改即可。

相关推荐
米奇妙妙wuu12 分钟前
react使用sse流实现chat大模型问答,补充css样式
前端·css·react.js
傻小胖17 分钟前
React 生命周期完整指南
前端·react.js
梦境之冢1 小时前
axios 常见的content-type、responseType有哪些?
前端·javascript·http
racerun1 小时前
vue VueResource & axios
前端·javascript·vue.js
m0_548514771 小时前
前端Pako.js 压缩解压库 与 Java 的 zlib 压缩与解压 的互通实现
java·前端·javascript
AndrewPerfect1 小时前
xss csrf怎么预防?
前端·xss·csrf
Calm5501 小时前
Vue3:uv-upload图片上传
前端·vue.js
浮游本尊1 小时前
Nginx配置:如何在一个域名下运行两个网站
前端·javascript
m0_748239831 小时前
前端bug调试
前端·bug
m0_748232921 小时前
[项目][boost搜索引擎#4] cpp-httplib使用 log.hpp 前端 测试及总结
前端·搜索引擎