react-router会包含一些react-native的内容,web开发并不需要
npm install react-router-dom
BrowserRouter或HashRouter
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import { HashRouter } from 'react-router-dom';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
);
包裹所有的Route,在其中匹配一个路由
home
Router5.x使用的是Switch组件
{/* 重定向 */}
Route用于路径的匹配
to属性:Link中最重要的属性,用于设置跳转到的路径
import React, { PureComponent } from 'react';
import { Route, Routes, Link } from 'react-router-dom';
import Home from './pages/Home.jsx';
import About from './pages/About.jsx';
export class App extends PureComponent {
render() {
return (
{/* 设置组件跳转 */}
首页
关于
{/* 映射关系 : path => Component */}
} />
} />
} />
footer
);
}
}
export default App;
NavLink是在Link基础之上增加了一些样式属性
认匹配成功时,NavLink就会添加上一个动态的active class
import React, { PureComponent } from 'react';
import { Route, Routes, NavLink } from 'react-router-dom';
import Home from './pages/Home.jsx';
import About from './pages/About.jsx';
export class App extends PureComponent {
render() {
return (
{/* 设置组件跳转 */}
首页
关于
{/* 映射关系 : path => Component */}
} />
} />
} />
footer
);
}
}
export default App;
Navigate用于路由的重定向,当这个组件出现时,就会执行跳转到对应的to路径中
Router5.x使用的 Redirect
import React, { PureComponent } from 'react';
import { Navigate } from 'react-router-dom';
export class Mine extends PureComponent {
constructor(props) {
super(props);
this.state = {
isLogin: false
};
}
login() {
this.setState({
isLogin: true
});
}
render() {
const { isLogin } = this.state;
return (
Mine
{/* 一旦出现Navigate,会自动跳转到对应页面 */}
{!isLogin ? : }
);
}
}
export default Mine;
用于显示默认显示的页面
{/* } /> */}
} />
} />
} />
} />
当随意输入一个地址,该地址无法匹配,则显示一个Not Found的页面
} />
} />
} />
} />
{/* 当前面的路由未匹配到时, 显示 NotFound 组件 */}
} />
这里创建home组件的嵌套
在App.jsx中,统一配置,router6.x之后路由配置最好写在一起
在home组件中进行配置
组件用于在父路由元素中作为子路由的占位元素
import React, { PureComponent } from 'react';
import { Link, Outlet } from 'react-router-dom';
export class Home extends PureComponent {
render() {
return (
Home
{/* 跳转按钮 */}
推荐
排行
{/* 占位组件 */}
);
}
}
export default Home;
在Router6.x版本之后,代码类的API都迁移到了hooks的写法 => useNavigate的Hook
hook只能在函数式组件中使用
import React from 'react';
import { Route, Routes, NavLink, Navigate, useNavigate } from 'react-router-dom';
import Home from './pages/Home.jsx';
import Recommand from './pages/components/Recommand.jsx';
import Ranking from './pages/components/Ranking.jsx';
import About from './pages/About.jsx';
import Mine from './pages/Mine.jsx';
import NotFound from './pages/NotFound.jsx';
// 1. 导入组件
import Category from './pages/Category.jsx';
import Profily from './pages/Profily.jsx';
export function App(props) {
// hooks 只能放在顶层中使用,不能放在嵌套函数、条件判断、循环中使用,否则会报错
const navigate = useNavigate();
function routerJump(path) {
// 4. 跳转
navigate(path);
}
return (
首页
关于
我的
{/* 3. 点击跳转 */}
{/* 映射关系 : path => Component */}
} />
}>
} />
} />
} />
} />
} />
{/* 2. 配置映射关系 */}
} />
} />
{/* 当前面的路由未匹配到时, 显示 NotFound 组件 */}
} />
footer
);
}
export default App;
如果要在类组件中使用,则需弄一个高级组件包裹一下
// 让类组件可以使用路由组件的API进行跳转
import { useNavigate } from 'react-router-dom';
export default function withRouter(WrapperComponent) {
return (props) => {
const navigate = useNavigate();
return ;
};
}
import React, { PureComponent } from 'react';
import { Route, Routes, NavLink, Navigate } from 'react-router-dom';
import About from './pages/About.jsx';
import NotFound from './pages/NotFound.jsx';
// 1. 导入组件
import Category from './pages/Category.jsx';
import Profily from './pages/Profily.jsx';
// 2. 导入高阶组件
import withRouter from './hoc/withRouter.js';
export class App extends PureComponent {
routerJump(path) {
// 5. 拿到增强到的router,设置跳转
const { router } = this.props;
router.navigate(path);
}
render() {
return (
关于
{/* 4. 点击跳转 */}
{/* 映射关系 : path => Component */}
} />
} />
{/* 2. 配置映射关系 */}
} />
} />
{/* 当前面的路由未匹配到时, 显示 NotFound 组件 */}
} />
footer
);
}
}
// 3. 使用高阶组件
export default withRouter(App);
} />
import React, { PureComponent } from 'react';
import withRouter from '../hoc/withRouter';
export class Category extends PureComponent {
constructor(props) {
super(props);
this.state = {
arrList: [22222, 33333, 44444, 55555]
};
}
itemClick(id) {
const { router } = this.props;
// 跳转到详情页
router.navigate(`/detail/${id}`);
}
render() {
const { arrList } = this.state;
return (
<>
Category
{arrList.map((item, index) => {
return (
- this.itemClick(item)} key={index}>
{item}
);
})}
>
);
}
}
export default withRouter(Category);
// 让类组件可以使用路由组件的API
import { useNavigate, useParams } from 'react-router-dom';
export default function withRouter(WrapperComponent) {
return (props) => {
// 1. 跳转对象
const navigate = useNavigate();
// 2. 动态路由的参数 /detail/:id
const params = useParams();
return ;
};
}
import React, { PureComponent } from 'react';
import withRouter from '../hoc/withRouter';
export class Detail extends PureComponent {
render() {
// 1. 通过 withRouter 高阶组件,可以获取到路由信息
const { router } = this.props;
return (
<>
Detail
{/* 2. 通过 router.params 获取到路由参数 */}
id: {router.params.id}
>
);
}
}
export default withRouter(Detail);
import React, { PureComponent } from 'react';
import { Route, Routes, NavLink, Navigate } from 'react-router-dom';
// 2. 导入高阶组件
import withRouter from './hoc/withRouter.js';
import Detail from './pages/Detail.jsx';
import Category from './pages/Category.jsx';
export class App extends PureComponent {
routerJump(path) {
const { router } = this.props;
router.navigate(path);
}
render() {
return (
分类
{/* 5. 携带参数,使用query传参 */}
详情
{/* 4. 映射关系 : path => Component */}
} />
} />
} />
footer
);
}
}
// 3. 使用高阶组件
export default withRouter(App);
// 让类组件可以使用路由组件的API
import { useNavigate, useParams, useLocation, useSearchParams } from 'react-router-dom';
export default function withRouter(WrapperComponent) {
return (props) => {
// 1. 跳转对象
const navigate = useNavigate();
// 2. 动态路由的参数 /detail/:id
const params = useParams();
// 3. 查询字符串的参数 /detail?id=1&name=jack
// 3.1.1 通过useLocation获取查询字符串
// const lacationSearchs = useLocation().search;
// console.log('searchParams', lacationSearchs); // ?name=coder&age=18 => 不太好用
// 3.1.2 通过URLSearchParams获取查询字符串
// const lacationSearchParams = new URLSearchParams(lacationSearchs);
// console.log('searchParams', lacationSearchParams.get('name')); // coder
// 3.2.1 通过useSearchParams获取查询字符串
const [searchParams, setSearchParams] = useSearchParams();
// console.log('searchParams', searchParams.get('name')); // coder
const query = Object.fromEntries(searchParams.entries()); // 可直接转换为对象,Object.fromEntries(searchParams)
// console.log('searchParams', query); // {name: "coder", age: "18"}
return ;
};
}
import React, { PureComponent } from 'react';
import withRouter from '../hoc/withRouter';
export class Detail extends PureComponent {
render() {
// 1. 通过 withRouter 高阶组件,可以获取到路由信息
const { router } = this.props;
const { name, age } = router.query;
return (
<>
Detail
{/* 2. 通过 router.params 获取到路由参数 */}
name: {name}
age: {age}
>
);
}
}
export default withRouter(Detail);
目前所有的路由定义都是直接使用Route组件,并且添加属性来完成的
但是这样的方式会让路由变得非常混乱,我们希望将所有的路由配置放到一个地方进行集中管理:
index.js
const routes = [];
export default routes;
import React from 'react';
import { NavLink, useNavigate, useRoutes } from 'react-router-dom';
// 1. 导入路由相关的组件
import routes from './router';
export function App(props) {
const navigate = useNavigate();
function routerJump(path) {
navigate(path);
}
return (
首页
关于
我的
{/*
} />
}>
} />
} />
} />
} />
} />
} />
} />
} />
*/}
{/* 2. 使用路由组件,渲染路由,并且传入路由配置 */}
{useRoutes(routes)}
footer
);
}
export default App;
import React, { Suspense } from 'react';
import ReactDOM from 'react-dom/client';
import App from './App.jsx';
import { HashRouter } from 'react-router-dom';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
{/*
Suspense组件用于在组件渲染时显示一个fallback组件,直到该组件加载完成为止
fallback属性用于指定fallback组件,可以是任何react元素,可以是一个加载动画,也可以是一个加载提示文字
当异步组件加载完成后,fallback组件会被卸载,然后渲染异步组件
*/}
Loading...
// Desc: 路由配置文件
// 同步路由配置,没进行分包处理
// import Home from '../pages/Home.jsx';
import Recommand from '../pages/components/Recommand.jsx';
import Ranking from '../pages/components/Ranking.jsx';
import About from '../pages/About.jsx';
import Mine from '../pages/Mine.jsx';
import NotFound from '../pages/NotFound.jsx';
import Category from '../pages/Category.jsx';
import Profily from '../pages/Profily.jsx';
import { Navigate } from 'react-router-dom';
// 异步路由配置,进行了分包处理 => 一般用于比较大的页面,比如登录页、注册页、首页等
import { lazy } from 'react';
// import => 会将整个文件加载进来,然后再从中导出需要的部分, 会导致整个文件被加载进来,会增加首屏加载时间 => 是webpack的语法