一、Router6相关概念与基础
1.安装react路由所需要的组件,react-dom
和react-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等常用属性
BrowserRouter
: HTML5 History API 来管理应用程序的路由。它是react-router
库中的Router
组件的一种实现,用于提供路由功能并确保应用程序中的地址与当前路由状态同步。NavLink
: 用于创建导航链接。它是Link
组件的特殊版本,允许你在当前页面的 URL 与给定的链接匹配时为链接应用额外的样式或类名。Route
: 用于定义应用程序中的路由和相应的组件。它匹配当前的 URL,并渲染与之匹配的组件。你可以使用path
属性来指定要匹配的 URL 路径,然后使用element
属性来指定与之匹配时要渲染的组件。Routes
: 用于将多个Route
组件包裹在一起,从而定义应用程序的路由层次结构。你可以在Routes
组件中定义多个嵌套的Route
组件,每个Route
组件定义一个特定的路径和相应的组件。createRoot
: 创建一个根ReactDOM
渲染容器。与常规的ReactDOM.render
方法不同,可以用于启用React
的异步渲染模式(Concurrent Mode),从而提高应用程序的渲染性能和交互体验。
2.了解路由的工作模式
react-router6包含两种路由:BrowserRouter
和HashRouter
。
- HashRouter:使用 URL 的哈希值实现(http://localhost:3000/#/first)
- 原理:监听 window 的
hashchange
事件来实现的
- 原理:监听 window 的
- (推荐)BrowserRouter:使用 H5 的 history API 实现(http://localhost:3000/first)
- 原理:监听 window 的
popstate
事件来实现的
- 原理:监听 window 的
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.路由的执行过程
- 点击 Link 组件(a标签),修改了浏览器地址栏中的 url
- React 路由监听到地址栏 url 的变化 hashChange/popState
- React 路由内部遍历所有 Route 组件,使用路由规则(path)与 pathname进行匹配
- 当路由规则(path)能够匹配地址栏中的 pathname时,就展示该 Route 组件的内容
其中Link
和NavLink
都是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等状态管理库中存放的,到时候根据业务需要更改即可。