目录:
- 课程说明
- 一级路由
- 重定向
- NavLink高亮
- useRoutes路由表
- 嵌套路由
- 路由的params参数
- 路由的search参数
- 路由的state参数
- 编程式路由导航
- useRouterContext
- useNavigationType
- useOutlet
- useResolvedPath()
- 总结
- 项目地址
1.课程说明
概述
- React Router以三个不同的包发布到npm 上,它们分别为:
- 1.react-router:路由的核心库,提供了很多的:组件、钩子。
- 2.react-router-dom:包含react-router所有内容,并添加一些专门用于DOM的组件,例如<BrowserRouter>等。
- 3. react-router-native:包括react-router所有内容,并添加一些专门用于ReactNative的API例如:<NativeRouter>等。
- 2.与React Router 5.x版本相比,改变了什么?
- 1.内置组件的变化:移除<Switch/>,新增<Routes/>等。
- ⒉.语法的变化: component={About]变为element={<About/>}等。
- 3.新增多个hook: useParams 、useNavigate 、useMatch 等。
- 4.官方明确推荐函数式组件了!!!
2.一级路由
About.jsx
import React from 'react';
function About(props) {
return (
<div>
<h3>我是About的内容</h3>
</div>
);
}
export default About;
Home.jsx
import React from 'react';
function Home(props) {
return (
<div>
<h3>我是Home的内容</h3>
</div>
);
}
export default Home;
App.js
import React from 'react';
import {NavLink, Routes, Route} from "react-router-dom";
import About from "./pages/About";
import Home from "./pages/Home";
function App(props) {
return (
<div>
<div className="row">
<div className="col-xs-offset-2 col-xs-8">
<div className="page-header"><h2>React Router Demo</h2></div>
</div>
</div>
<div className="row">
<div className="col-xs-2 col-xs-offset-2">
<div className="list-group">
<NavLink className="list-group-item" to="/about">About</NavLink>
<NavLink className="list-group-item" to="/home">Home</NavLink>
</div>
</div>
<div className="col-xs-6">
<div className="panel">
<div className="panel-body">
<Routes>
<Route path="/about" element={<About></About>}></Route>
<Route path="/home" element={<Home></Home>}></Route>
</Routes>
</div>
</div>
</div>
</div>
</div>
);
}
export default App;
index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import {BrowserRouter} from "react-router-dom";
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<BrowserRouter>
<App/>
</BrowserRouter>
);
3.重定向
App.js
import React from 'react';
import {NavLink, Routes, Route, Navigate} from "react-router-dom";
import About from "./pages/About";
import Home from "./pages/Home";
function App(props) {
return (
<div>
<div className="row">
<div className="col-xs-offset-2 col-xs-8">
<div className="page-header"><h2>React Router Demo</h2></div>
</div>
</div>
<div className="row">
<div className="col-xs-2 col-xs-offset-2">
<div className="list-group">
<NavLink className="list-group-item" to="/about">About</NavLink>
<NavLink className="list-group-item" to="/home">Home</NavLink>
</div>
</div>
<div className="col-xs-6">
<div className="panel">
<div className="panel-body">
<Routes>
<Route path="/ABOUT" caseSensitive element={<About></About>}></Route>
<Route path="/home" element={<Home></Home>}></Route>
<Route path="/" element={<Navigate to="/about"/>}></Route>
</Routes>
</div>
</div>
</div>
</div>
</div>
);
}
export default App;
Home.jsx
import React, {useState} from 'react';
import {Navigate} from "react-router-dom";
function Home(props) {
const [sum, setSum] = useState(1)
return (
<div>
<h3>我是Home的内容</h3>
{sum === 2 ? <Navigate to="/about/" replace={true}/> : <h4>当前sum的值是:{sum}</h4>}
<button onClick={() => setSum(2)}>点我将sum变为2</button>
</div>
);
}
export default Home;
4.NavLink高亮
App.js
import React from 'react';
import {NavLink, Routes, Route, Navigate} from "react-router-dom";
import About from "./pages/About";
import Home from "./pages/Home";
function App(props) {
function computedClassName({isActive}) {
return isActive ? 'list-group-item atguigu' : 'list-group-item'
}
return (
<div>
<div className="row">
<div className="col-xs-offset-2 col-xs-8">
<div className="page-header"><h2>React Router Demo</h2></div>
</div>
</div>
<div className="row">
<div className="col-xs-2 col-xs-offset-2">
<div className="list-group">
<NavLink className={computedClassName} to="/about">About</NavLink>
<NavLink className={computedClassName} to="/home">Home</NavLink>
</div>
</div>
<div className="col-xs-6">
<div className="panel">
<div className="panel-body">
<Routes>
<Route path="/about" element={<About></About>}></Route>
<Route path="/home" element={<Home></Home>}></Route>
<Route path="/" element={<Navigate to="/about"/>}></Route>
</Routes>
</div>
</div>
</div>
</div>
</div>
);
}
export default App;
About.jsx
import React from 'react';
function About(props) {
return (
<div>
<h3>我是About的内容</h3>
</div>
);
}
export default About;
Home.jsx
import React from 'react';
function Home(props) {
return (
<div>
<h3>我是Home的内容</h3>
</div>
);
}
export default Home;
5.useRoutes路由表
route/index.js
import About from "../pages/About";
import Home from "../pages/Home";
import {Navigate} from "react-router-dom";
export default [
{
path: '/about',
element: <About></About>
},
{
path: '/home',
element: <Home></Home>
},
{
path: '/',
element: <Navigate to="/about"></Navigate>
},
]
App.js
import React from 'react';
import {NavLink, useRoutes} from "react-router-dom";
import routes from "./routes";
function App(props) {
const element = useRoutes(routes)
return (
<div>
<div className="row">
<div className="col-xs-offset-2 col-xs-8">
<div className="page-header"><h2>React Router Demo</h2></div>
</div>
</div>
<div className="row">
<div className="col-xs-2 col-xs-offset-2">
<div className="list-group">
<NavLink className="list-group-item" to="/about">About</NavLink>
<NavLink className="list-group-item" to="/home">Home</NavLink>
</div>
</div>
<div className="col-xs-6">
<div className="panel">
<div className="panel-body">
{/*<Routes>*/}
{/* <Route path="/about" element={<About></About>}></Route>*/}
{/* <Route path="/home" element={<Home></Home>}></Route>*/}
{/* <Route path="/" element={<Navigate to="/about"/>}></Route>*/}
{/*</Routes>*/}
{element}
</div>
</div>
</div>
</div>
</div>
);
}
export default App;
6.嵌套路由
App.js
import React from 'react';
import {NavLink, useRoutes} from "react-router-dom";
import routes from "./routes";
function App(props) {
const element = useRoutes(routes)
return (
<div>
<div className="row">
<div className="col-xs-offset-2 col-xs-8">
<div className="page-header"><h2>React Router Demo</h2></div>
</div>
</div>
<div className="row">
<div className="col-xs-2 col-xs-offset-2">
<div className="list-group">
<NavLink className="list-group-item" to="/about">About</NavLink>
<NavLink className="list-group-item" end to="/home">Home</NavLink>
</div>
</div>
<div className="col-xs-6">
<div className="panel">
<div className="panel-body">
{/*<Routes>*/}
{/* <Route path="/about" element={<About></About>}></Route>*/}
{/* <Route path="/home" element={<Home></Home>}></Route>*/}
{/* <Route path="/" element={<Navigate to="/about"/>}></Route>*/}
{/*</Routes>*/}
{element}
</div>
</div>
</div>
</div>
</div>
);
}
export default App;
route/index.js
import About from "../pages/About";
import Home from "../pages/Home";
import {Navigate} from "react-router-dom";
import News from "../pages/News";
import Message from "../pages/Message";
export default [
{
path: '/about',
element: <About></About>
},
{
path: '/home',
element: <Home></Home>,
children: [
{
path: 'news',
element: <News></News>
},
{
path: 'message',
element: <Message></Message>
}
]
},
{
path: '/',
element: <Navigate to="/about"></Navigate>
},
]
News.jsx
import React from 'react';
function News(props) {
return (
<div>
<ul>
<li>news001</li>
<li>news002</li>
<li>news003</li>
</ul>
</div>
);
}
export default News;
Message.jsx
import React from 'react';
function Message(props) {
return (
<div>
<ul>
<li>
<a href="/message1">message001</a>
</li>
<li>
<a href="/message2">message002</a>
</li>
<li>
<a href="/message/3">message003</a>
</li>
</ul>
</div>
);
}
export default Message;
Home.jsx
import React from 'react';
import {NavLink, Outlet} from "react-router-dom";
function Home(props) {
return (
<div>
<h2>Home组件内容</h2>
<div>
<ul className="nav nav-tabs">
<li>
<NavLink className="list-group-item" to="news">News</NavLink>
{/*<NavLink className="list-group-item" to="./news">News</NavLink>*/}
{/*<NavLink className="list-group-item" to="/home/news">News</NavLink>*/}
</li>
<li>
<NavLink className="list-group-item " to="message">Message</NavLink>
{/*<NavLink className="list-group-item " to="./message">Message</NavLink>*/}
{/*<NavLink className="list-group-item " to="/home/message">Message</NavLink>*/}
</li>
</ul>
<Outlet></Outlet>
</div>
</div>
);
}
export default Home;
About.jsx
import React from 'react';
function About(props) {
return (
<div>
<h3>我是About的内容</h3>
</div>
);
}
export default About;
7.路由的params参数
Detail.jsx
import React from 'react';
import {useMatch, useParams} from "react-router-dom";
function Detail(props) {
const {id, title, content} = useParams()
const x = useMatch('/home/message/detail/:id/:title/:content')
console.log(x)
return (
<div>
<ul>
<li>消息编号:{id}</li>
<li>消息标题:{title}</li>
<li>消息内容:{content}</li>
</ul>
</div>
);
}
export default Detail;
Message.jsx
import React, {useState} from 'react';
import {Link, Outlet} from "react-router-dom";
function Message(props) {
const [messages] = useState([
{id: '001', title: '消息1', content: '锄禾日当午'},
{id: '002', title: '消息2', content: '汗滴禾下土'},
{id: '003', title: '消息3', content: '谁知盘中餐'},
{id: '004', title: '消息4', content: '粒粒皆辛苦'},
])
return (
<div>
<ul>
{
messages.map((m) => {
return (
<li key={m.id}>
<Link to={`detail/${m.id}/${m.title}/${m.content}`}>{m.title}</Link>
</li>
)
})
}
</ul>
<hr></hr>
<Outlet></Outlet>
</div>
);
}
export default Message;
routes/index.js
import About from "../pages/About";
import Home from "../pages/Home";
import {Navigate} from "react-router-dom";
import News from "../pages/News";
import Message from "../pages/Message";
import Detail from "../pages/Detail";
export default [
{
path: '/about',
element: <About></About>
},
{
path: '/home',
element: <Home></Home>,
children: [
{
path: 'news',
element: <News></News>
},
{
path: 'message',
element: <Message></Message>,
children: [
{
path: 'detail/:id/:title/:content',
element: <Detail></Detail>
}
]
}
]
},
{
path: '/',
element: <Navigate to="/about"></Navigate>
},
]
8.路由的search参数
Detail.jsx
import React from 'react';
import {useLocation, useSearchParams} from "react-router-dom";
function Detail(props) {
const [search, setSearch] = useSearchParams()
const id = search.get('id')
const title = search.get('title')
const content = search.get('content')
const x = useLocation()
console.log(x)
return (
<div>
<ul>
<li>
<button onClick={() => setSearch('id=008&title=哈哈&content=嘻嘻')}>点我更新一下收到的search参数
</button>
</li>
<li>消息编号:{id}</li>
<li>消息标题:{title}</li>
<li>消息内容:{content}</li>
</ul>
</div>
);
}
export default Detail;
Message.jsx
import React, {useState} from 'react';
import {Link, Outlet} from "react-router-dom";
function Message(props) {
const [messages] = useState([
{id: '001', title: '消息1', content: '锄禾日当午'},
{id: '002', title: '消息2', content: '汗滴禾下土'},
{id: '003', title: '消息3', content: '谁知盘中餐'},
{id: '004', title: '消息4', content: '粒粒皆辛苦'},
])
return (
<div>
<ul>
{
messages.map((m) => {
return (
<li key={m.id}>
{/*<Link to={`detail/${m.id}/${m.title}/${m.content}`}>{m.title}</Link> */}
<Link to={`detail?id=${m.id}&title=${m.title}&content=${m.content}`}>{m.title}</Link>
</li>
)
})
}
</ul>
<hr></hr>
<Outlet></Outlet>
</div>
);
}
export default Message;
index.js
import About from "../pages/About";
import Home from "../pages/Home";
import {Navigate} from "react-router-dom";
import News from "../pages/News";
import Message from "../pages/Message";
import Detail from "../pages/Detail";
export default [
{
path: '/about',
element: <About></About>
},
{
path: '/home',
element: <Home></Home>,
children: [
{
path: 'news',
element: <News></News>
},
{
path: 'message',
element: <Message></Message>,
children: [
{
path: 'detail',
element: <Detail></Detail>
}
]
}
]
},
{
path: '/',
element: <Navigate to="/about"></Navigate>
},
]
9.路由的state参数
Detail.jsx
import React from 'react';
import {useLocation} from "react-router-dom";
function Detail(props) {
const {state: {id, title, content}} = useLocation()
return (
<div>
<ul>
<li>消息编号:{id}</li>
<li>消息标题:{title}</li>
<li>消息内容:{content}</li>
</ul>
</div>
);
}
export default Detail;
Message.jsx
import React, {useState} from 'react';
import {Link, Outlet} from "react-router-dom";
function Message(props) {
const [messages] = useState([
{id: '001', title: '消息1', content: '锄禾日当午'},
{id: '002', title: '消息2', content: '汗滴禾下土'},
{id: '003', title: '消息3', content: '谁知盘中餐'},
{id: '004', title: '消息4', content: '粒粒皆辛苦'},
])
return (
<div>
<ul>
{
messages.map((m) => {
return (
<li key={m.id}>
{/*<Link to={`detail/${m.id}/${m.title}/${m.content}`}>{m.title}</Link> */}
{/*<Link to={`detail?id=${m.id}&title=${m.title}&content=${m.content}`}>{m.title}</Link>*/}
<Link to="detail"
state={{id: m.id, title: m.title, content: m.content}}>{m.title}</Link>
</li>
)
})
}
</ul>
<hr></hr>
<Outlet></Outlet>
</div>
);
}
export default Message;
routes/index.js
import About from "../pages/About";
import Home from "../pages/Home";
import {Navigate} from "react-router-dom";
import News from "../pages/News";
import Message from "../pages/Message";
import Detail from "../pages/Detail";
export default [
{
path: '/about',
element: <About></About>
},
{
path: '/home',
element: <Home></Home>,
children: [
{
path: 'news',
element: <News></News>
},
{
path: 'message',
element: <Message></Message>,
children: [
{
path: 'detail',
element: <Detail></Detail>
}
]
}
]
},
{
path: '/',
element: <Navigate to="/about"></Navigate>
},
]
10.编程式路由导航
Header.jsx
import React from 'react';
import {useNavigate} from "react-router-dom";
function Header(props) {
const navigate = useNavigate()
function back() {
navigate(-1)
}
function forward() {
navigate(1)
}
return (
<div>
<div className="col-xs-offset-2 col-xs-8">
<div className="page-header">
<h2>React Router Demo</h2>
<button onClick={back}>后退</button>
<button onClick={forward}>前进</button>
</div>
</div>
</div>
);
}
export default Header;
Message.jsx
import React, {useState} from 'react';
import {Link, Outlet, useNavigate} from "react-router-dom";
function Message(props) {
const [messages] = useState([
{id: '001', title: '消息1', content: '锄禾日当午'},
{id: '002', title: '消息2', content: '汗滴禾下土'},
{id: '003', title: '消息3', content: '谁知盘中餐'},
{id: '004', title: '消息4', content: '粒粒皆辛苦'},
])
const navigate = useNavigate()
function showDetail(m) {
navigate('detail', {replace: false, state: {id: m.id, title: m.title, content: m.content}})
}
return (
<div>
<ul>
{
messages.map((m) => {
return (
<li key={m.id}>
{/*<Link to={`detail/${m.id}/${m.title}/${m.content}`}>{m.title}</Link> */}
{/*<Link to={`detail?id=${m.id}&title=${m.title}&content=${m.content}`}>{m.title}</Link>*/}
<Link to="detail"
state={{id: m.id, title: m.title, content: m.content}}>{m.title}</Link>
<button onClick={() => showDetail(m)}>查看详情</button>
</li>
)
})
}
</ul>
<hr></hr>
<Outlet></Outlet>
</div>
);
}
export default Message;
App.js
import React from 'react';
import {NavLink, useRoutes} from "react-router-dom";
import routes from "./routes";
import Header from "./components/Header";
function App(props) {
const element = useRoutes(routes)
return (
<div>
<div className="row">
<Header></Header>
</div>
<div className="row">
<div className="col-xs-2 col-xs-offset-2">
<div className="list-group">
<NavLink className="list-group-item" to="/about">About</NavLink>
<NavLink className="list-group-item" to="/home">Home</NavLink>
</div>
</div>
<div className="col-xs-6">
<div className="panel">
<div className="panel-body">
{/*<Routes>*/}
{/* <Route path="/about" element={<About></About>}></Route>*/}
{/* <Route path="/home" element={<Home></Home>}></Route>*/}
{/* <Route path="/" element={<Navigate to="/about"/>}></Route>*/}
{/*</Routes>*/}
{element}
</div>
</div>
</div>
</div>
</div>
);
}
export default App;
11.useRouterContext
- uselnRouterContext()
- 作用:如果组件在<Router>的上下文中呈现,则useInRouterContext钩子返回true,否则返回false。
index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import {BrowserRouter} from "react-router-dom";
import Demo from "./components/Demo";
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<Demo></Demo>,
<BrowserRouter>
<App/>
</BrowserRouter>
);
App.js
import React from 'react';
import {NavLink, useInRouterContext, useRoutes} from "react-router-dom";
import routes from "./routes";
import Header from "./components/Header";
function App(props) {
const element = useRoutes(routes)
console.log('@',useInRouterContext())
return (
<div>
<div className="row">
<Header></Header>
</div>
<div className="row">
<div className="col-xs-2 col-xs-offset-2">
<div className="list-group">
<NavLink className="list-group-item" to="/about">About</NavLink>
<NavLink className="list-group-item" to="/home">Home</NavLink>
</div>
</div>
<div className="col-xs-6">
<div className="panel">
<div className="panel-body">
{/*<Routes>*/}
{/* <Route path="/about" element={<About></About>}></Route>*/}
{/* <Route path="/home" element={<Home></Home>}></Route>*/}
{/* <Route path="/" element={<Navigate to="/about"/>}></Route>*/}
{/*</Routes>*/}
{element}
</div>
</div>
</div>
</div>
</div>
);
}
export default App;
Demo.jsx
import React from 'react';
import {useInRouterContext} from "react-router-dom";
function Demo(props) {
console.log(useInRouterContext())
return (
<div>
demo
</div>
);
}
export default Demo;
Header.jsx
import React from 'react';
import {useInRouterContext, useNavigate} from "react-router-dom";
function Header(props) {
const navigate = useNavigate()
console.log(useInRouterContext())
function back() {
navigate(-1)
}
function forward() {
navigate(1)
}
return (
<div>
<div className="col-xs-offset-2 col-xs-8">
<div className="page-header">
<h2>React Router Demo</h2>
<button onClick={back}>后退</button>
<button onClick={forward}>前进</button>
</div>
</div>
</div>
);
}
export default Header;
12.useNavigationType
- useNavigationType()
- 作用:返回当前的导航类型((用户是如何来到当前页面的)。
- 返回值:POP、PUSH、REPLACE]。
- 备注:PoP是指在浏览器中直接打开了这个路由组件(刷新页面)。
News.jsx
import React from 'react';
import {useNavigationType} from "react-router-dom";
function News(props) {
console.log(useNavigationType())
return (
<div>
<ul>
<li>news001</li>
<li>news002</li>
<li>news003</li>
</ul>
</div>
);
}
export default News;
13.useOutlet
- useOutlet()
- 作用:用来呈现当前组件中要渲染的嵌套路由。
- 示例代码:
const result = useoutlet( )
console.log( result)
//如果嵌套路由没有挂载,则result为null
//如果嵌套路由已经挂载,则展示嵌套的路由对象
Home.jsx
import React from 'react';
import {NavLink, Outlet, useOutlet} from "react-router-dom";
function Home(props) {
console.log(useOutlet())
return (
<div>
<h2>Home组件内容</h2>
<div>
<ul className="nav nav-tabs">
<li>
<NavLink className="list-group-item" to="news">News</NavLink>
</li>
<li>
<NavLink className="list-group-item " to="message">Message</NavLink>
</li>
</ul>
<Outlet></Outlet>
</div>
</div>
);
}
export default Home;
14.useResolvedPath()
- useResolvedPath()
- 作用:给定一个URL值,解析其中的: path、search、hash值。
News.jsx
import React from 'react';
import {useResolvedPath} from "react-router-dom";
function News(props) {
console.log(useResolvedPath('/user?id=001&name=tom#qwe'))
return (
<div>
<ul>
<li>news001</li>
<li>news002</li>
<li>news003</li>
</ul>
</div>
);
}
export default News;
15.总结:
2.Component
1. <BrowserRouter>
- 说明:<BrowserRouter>用于包裹整个应用。
- 示例代码:
-
import React from "react"; import ReactDOM from "react-dom" ; import { BrowserRouter } from "react-router-dom" ; ReactDOM.render( <BrowserRouter> {/*整体结构(通常为App组件)*/} </BrowserRouter> ,root );
2.<HashRouter>
- 说明:作用与<BrowserRouter>一样,但<HashRouter>修改的是地址栏的hash值。
- 备注:6.x版本中<HashRouter>、<BrowserRouter>的用法与5.x相同。
3.<Routes/> 与<Route/>
- v6版本中移出了先前的<Switch>,引入了新的替代者:<Routes>。
- <Routes>和<Route>要配合使用,且必须要用<Routes>包裹<Route>。
- <Route>相当于一个if语句,如果其路径与当前URL匹配,则呈现其对应的组件。
- <Route caseSensitive>属性用于指定:匹配时是否区分大小写(默认为false)。
- 当URL发生变化时,<Routes>都会查看其所有子<Route>元素以找到最佳匹配并呈现组件。
- <cRoute也可以嵌套使用,且可配合useRoutes()配置“路由表”,但需要通过<outlet>组件来渲染其子路由。
- 示例代码:
4.<Link>
- 作用:修改URL,且不发送网络请求(路由链接)。
5.<NavLink>
- 作用:与<Link>组件类似,且可实现导航的“高亮"效果。
- 示例代码:
6.<Navigate>
- 作用:只要<Navigate>组件被渲染,就会修改路径,切换视图。
- replace属性用于控制跳转模式(push或 replace,默认是push) 。
- 示例代码:
7. <outlet>
- 当<Route>产生嵌套时,渲染其对应的后续子路由。
3.Hooks
1.useRoutes()
- 作用:根据路由表,动态创建<Routes>和<Route> 。
2.useNavigate
- 作用:返回一个函数用来实现编程式导航。
- 示例代码:
3. useParams()
- 作用:回当前匹配路由的params参数,类似于5.x中的match.params .
- 示例代码:
4.useSearchParams()
- 作用:用于读取和修改当前位置的URL中的查询字符串。
- 返回一个包含两个值的数组,内容分别为:当前的seaech参数、更新search的函数。
- 示例代码:
5.useLocation()
- 作用:获取当前location信息,对标5.x中的路由组件的location属性。
- 示例代码:
6.useMatch()
- 作用:返回当前匹配信息,对标5.x中的路由组件的match属性。
- 示例代码:
16.项目地址
https://gitee.com/coderPatrickStar/react/tree/master/20231003