下载安装
yarn add react-router-dom
页面引入
import { NavLink, Route, Routes } from "react-router-dom";
说明:由于react使用路由和注册路由都需要在一个同一个BrowserRouter标签中进行写,既然脚手架下全部路由都需要这种包裹,那么可以直接在index.js将App外层用BrowserRouter标签包裹。
示例:<BrowserRouter><App /></BrowserRouter>
说明:声明式路由 相当于a标签 to=“/about” 目标路由,一般都是小写
示例:<Link" to="/home"></Link>
说明:会比Link多一个背景颜色,如果要自定义背景颜色可以使用activeClassName="orange"定义。(如果自定义颜色后点击时出现闪烁的问题,直接在样式的后面加上!import 无穷大,问题解决)
示例: <NavLink activeClassName="navActive" to="/about">About</Navlink>
说明:注册路由 两个参数 path=“/about” component={ About } path是路由地址,component是渲染的组件
示例:<Route path="/about" component={ About } />
说明:如果多个组件同时使用同个path出现多渲染了不必要的组件,那么就可以使用Switch,让他匹配到第一个之后终止向下匹配
示例:以下path为home只会注册Home组件,不会再向下执行替换覆盖原有的组件
<Switch>
<Route path="/home" component={Home} />
<Route path="/about" component={About} />
<Route path="/home" component={Test} />
</Switch>
说明:路由重定向 上来默认显示第一个路由
<Switch>
<Route path="/home" component={Home} />
<Route path="/about" component={About} />
<Redirect to="home" />
</Switch>
说明:路由中的子路由 子路由的目标路由(to=“/xxx/yyy”)和注册路由(path=“/xxx/yyy”)地址需要加上父级路由
<NavLink to="/home/news">News</NavLink>
<Switch>
<Route path="/home/news" component={News}></Route>
<Route path="/home/messages" component={Messages}></Route>
<Redirect to="/home/news" /> 这个重定向是页面进来默认选中第一个子路由
</Switch>
父组件跳转到子组件同时传参
模板字符串传value
<Link to={`/home/messages/mlist/${obj.id}/${obj.content}`}>Mlist</Link>
注册的路由传key
<Route path={'/home/messages/mlist/:id/:content'} component={Mlist} />
子组件接收
由于传递的参数保存在props里面,所以需要这样取
let propMlist = this.props.match.params
打印接收的对象: {id: '4', content: '4月21日服务器停机维护公告(风暴双雄新版本)'}
父组件跳转到子组件同时传参
模板字符串传value query模式
<Link to={`/about/messages/list?id=${obj.id}&content=${obj.content}`}>Mlist</Link>
注册的路由传key
<Route path="/about/news/list/" component={Mlist} />
子组件接收
由于传递的参数保存在props里面,所以需要这样取
let { search } = this.props.location;
// 由于返回的是格式不是我们对象key:value方式,所以引入第三方帮我们处理 yarn add qs
import qs from "qs";
// 格式化后返回的格式为{?id:1},需要去掉id的?所以需要替换掉
let temp = qs.parse(search.replace("?", ""));
打印接收的对象: {id: '4', content: '4月21日服务器停机维护公告(风暴双雄新版本)'}
父组件跳转到子组件同时传参
模板字符串传value
<Link to={{pathname: '/about/news/list',state: { id: obj.id, content: obj.content }}}>Mlist</Link>
注册的路由传key
<Route path="/about/news/list/" component={Mlist} />
子组件接收
由于传递的参数保存在props里面,所以需要这样取
let { id, content } = this.props.match.state
打印接收的对象: {id: '4', content: '4月21日服务器停机维护公告(风暴双雄新版本)'}
Routes:相当于之前的Switch,不同的是如果Route外层不包裹Routes页面会报错。
Route:由react-router5的component变为element,同时用表达式和标签进行渲染
Navigate:重定向
<Routes>
<Route path="/about" element={<About />}></Route>
<Route path="/" element={<Navigate to="/about" />} />
</Routes>
超链接颜色动态更改
参数为回调,回调的参数有isActive,如果当前链接被选中isActive则为true,反之false;可以通过形参解构获取然后三元判断。curActCls是选择时额外添加的颜色。
<NavLink className={({ isActive }) => isActive ? 'list-group-item curActCls' : 'list-group-item'}
to="/home">Home</NavLink>
优化版 封一个函数直接调用即可
function computedCls({ isActive }) {
return isActive ? 'list-group-item curActCls' : 'list-group-item';
}
<NavLink className={computedCls} to="/about">About</NavLink>
通过路由数组生成一个路由组件直接渲染页面
创建 route -> index.js
import { Navigate } from 'react-router-dom';
import About from '../About';
import Home from '../Home';
export default [
{
path: '/about',
element: <About />,
},
{
path: '/home',
element: <Home />,
},
// 重定向
{
path: '/',
element: <Navigate to="/about" />,
},
];
App.jsx
import { NavLink, useRoutes } from 'react-router-dom';
import routes from './pages/route';
// 将路由数组放进去生成路由组件进行页面渲染,这样可以省着写Routes和Route
const element = useRoutes(routes);
<NavLink to="/about">About</NavLink>
<div>{element}</div>
// 每个父组件中只要引入了路由子组件,那么该父组件就需要写OutLet标签,Outlet底层就是自动根据route.js中配置的路由逐层去找的,所以需要提前到route.js中配置好,然后App.jsx引入并用useRoutes实例出一个新路由组件,同时在App.jsx底部渲染,参考上面的useRoutes。
import { NavLink, Outlet } from 'react-router-dom';
<NavLink to="list">List</NavLink>
// 它就是简写了}>
<Outlet />
params接收方式:接收路由传递过来的参数,返回值是一个对象,可以通过解构获取
route -> index.js 配置路由文件
{
path: 'son/:id/:name/:content', // 接收参数
element: <Son />,
}
About.js 父组件 发送者
import React, { useState } from 'react';
import { Link, Outlet } from 'react-router-dom';
export default function List() {
const [mesArr] = useState([
{ id: '1', name: 'java', content: '后端语言' },
{ id: '2', name: 'javaScript', content: '脚本语言' },
{ id: '3', name: '.Net', content: '后端语言' },
]);
return (
<>
<ul>
{mesArr.map(obj => {
return (
<li key={obj.id}>
// 用模板字符串直接传递
<Link to={`son/${obj.id}/${obj.name}/${obj.content}`}>
{obj.id}--{obj.name}--{obj.content}
</Link>
</li>
);
})}
</ul>
<hr />
<Outlet />
</>
);
}
List.js 子组件 接收方
import React from 'react';
import { useParams } from 'react-router-dom';
export default function Son() {
// useParams()返回一个接收对象,可直接解构获取
const { id, name, content } = useParams();
return (
<div>
<p>id:{id}</p>
<p>编程语言:{name}</p>
<p>内容:{content}</p>
</div>
);
}
search:类似于浏览器的query传参方式 ?id=1&name=jack
发送者:类似query方式传
接收方:引入useSearchParams, 用search.get(‘id’) 获取指定的属性
route -> index.js 配置路由文件
{
path: 'son', // 接收参数就不用传入指定属性名了
element: <Son />,
}
About.js 发送者
import React, { useState } from 'react';
import { Link, Outlet } from 'react-router-dom';
export default function List() {
const [mesArr] = useState([
{ id: '1', name: 'java', content: '后端语言' },
{ id: '2', name: 'javaScript', content: '脚本语言' },
{ id: '3', name: '.Net', content: '后端语言' },
]);
return (
<div>
<ul>
{mesArr.map(obj => {
return (
<li key={obj.id}>
// 区别在于用类似query方式传参
<Link
to={`son/?id=${obj.id}/&name=${obj.name}/&content=${obj.content}`}
>
{obj.id}--{obj.name}--{obj.content}
</Link>
</li>
);
})}
</ul>
<hr />
<Outlet />
</div>
);
}
Son.js 接收方 需要用search.get获取每个传递过来的属性
import React from 'react';
import { useSearchParams } from 'react-router-dom';
export default function Son() {
const [search] = useSearchParams();
const id = search.get('id');
const name = search.get('name');
const content = search.get('content');
return (
<div>
<p>id:{id}</p>
<p>编程语言:{name}</p>
<p>内容:{content}</p>
</div>
);
}
它就是react-router5的state,在Link标签中用state={{id:1}} 进行传参,用useLocation接收取返回对象中的state对象
About.jsx 发送者
<li key={obj.id}>
// state={{}} 这样传
<Link
to="son"
state={{
id: obj.id,
name: obj.name,
content: obj.content,
}}
>
{obj.id}--{obj.name}--{obj.content}
</Link>
</li>
Son.jsx 接收方
import React from 'react';
import { useLocation } from 'react-router-dom';
export default function Son() {
const { state } = useLocation();
console.log(state); // {id: '2', name: 'javaScript', content: '脚本语言'}
return (
<div>
<p>{state.id}</p>
<p>{state.name}</p>
<p>{state.content}</p>
</div>
);
}
实例出一个重定向函数,两个参数,函数和对象
Son.js 点击按钮就重定向到home路由,写法类似于微信小程序的路由跳转
import React, { useState } from 'react';
import { useNavigate } from 'react-router-dom';
export default function Son() {
const [count] = useState({ id: 1, name: 'jack', content: '测试用例' });
const navigate = useNavigate();
function linkFN(obj) {
// 关键点
navigate('/home', {
state: {
id: obj.id,
name: obj.name,
content: obj.content,
},
});
}
return (
<div>
<button onClick={() => linkFN(count)}>点我跳转到listTwo</button>
</div>
);
}
Home.js 接收方 由于对方是用state传参方式,所以需要用useLocation接收
import React from 'react';
import { useLocation } from 'react-router-dom';
export default function Home() {
const { state } = useLocation();
return (
<div>
<h1>Home</h1>
<ul className="nav nav-tabs">
// 如果state有值说明有人跳转过来同时携带参数来了,反之显示文本
{!state
? '这是Home组件'
: `${state.id}
${state.name}
${state.content}`}
</ul>
</div>
);
}
// 还可以做回退和前进
function backC() {
navigate(-1);
}
function forwardC() {
navigate(1);
}