学习目标:掌握ReactRouter的基本使用
目录
一、domo
先做个小domo感受一下:要实现有两个控制页面的按钮(首页和关于)点击按钮就跳转到对应的页面
1、安装 react-router包
npm add react-router-dom@6
2、代码
// 导入两个组件
import Home from "./Home"
import About from "./About"
// 引入必要的内置组件
import { BrowserRouter, Routes, Route, Link } from 'react-router-dom'
function App(){
return(
<div className="App">
{/* 声明当前要用一个非hash模式的路由 */}
<BrowserRouter>
{/*指定跳转的组件 to表示要跳转的路径 */}
<Link to="/"><button>首页</button></Link>
<span> | </span>
<Link to="/about"><button>关于</button></Link>
{/* 路由出口,路由对应的组件会在这里进行渲染 */}
<Routes>
{/* 指定路径和组件的对应关系 path是路径,element是组件 */}
<Route path="/" element={<Home />}></Route>
<Route path="/about" element={<About />}></Route>
</Routes>
</BrowserRouter>
</div>
)
}
export default App;
二、核心标签详解
1、BrowerRouter
声明项目中路由所采用的模式,一个React应用只需要使用一次
模式 | 实现方式 | 路由url表现 |
HashRouter | 监听url hash值实现 | http://localhost:3000/#/about |
BrowerRouter | h5的 history.pushState API实现 | http://localhost:3000/about |
2、Link
用于指定导航链接,完成声明式的路由跳转 类似于 <router-link/> ,to的值为和组件进行绑定的路径
<Link to="/"><button>首页</button></Link>
3、Routes
提供一个路由出口,组件内部会存在多个内置的Route组件,类比 router-view,满足条件的路由会被渲染到组件内部(所谓的满足条件就是路径对的上)
<Routes>
{/* 指定路径和组件的对应关系 path是路径,element是组件 */}
<Route path="/" element={<Home />}></Route>
<Route path="/about" element={<About />}></Route>
</Routes>
4、Route
用于定义路由路径和渲染组件的对应关系 [element:react体系内 把组件叫做react element]
<Route path="/about" element={<About />}></Route>
三、编程式导航
通过js编程的方式进行路由页面跳转
1、代码示例
在首页中添加按钮,点击后跳转到关于页面
import { useNavigate, Link} from "react-router-dom"
function Home(){
const navigate = useNavigate()
return(
<div>
<div>这是首页啦</div>
{/* 函数式 */}
<button onClick={()=>navigate('/about')}>跳转到关于页面</button>
{/* 声明式 */}
<Link to="/about"><button>跳转到关于页面</button></Link>
</div>
)
}
export default Home
2、总结步骤
- 导入一个 useNavigate 钩子函数
- 执行 useNavigate 函数 得到 跳转函数
- 在事件中执行跳转函数完成路由跳转
3、扩展
如果在跳转时不想添加历史记录,可以添加额外参数replace 为true
navigate('/about', { replace: true } )
四、路由传参
1、searchParams传参
(1)传参
<button onClick={()=>navigate('/about?id=1')}>跳转到关于页面</button>
(2)取参
// 先导入
import { useSearchParams } from "react-router-dom"
function About(){
// 执行函数
let [params] = useSearchParams()
// 使用get方法,获取对应的参数
let id = params.get('id')
return(
<div>这是关于页面啦{id}</div>
)
}
export default About
2、params传参
(1)传参
<button onClick={()=>navigate('/about/1/kk')}>跳转到关于页面</button>
一个斜杠一个坑
<Route path="/about/:id/:name" element={<About />}></Route>
(2)取参
// 先导入
import { useParams } from "react-router-dom"
function About(){
// 执行函数——这里不用解构
let params = useParams()
// 不用调用参数,对象的属性直接对应
let id = params.id
let name = params.name
return(
<div>这是关于页面啦{id} and {name}</div>
)
}
export default About
五、嵌套路由
1、两层嵌套
(1)实现效果
(2)代码实现
(1)首先要有两个页面,分别是看板和文章,示例如下:
function Board(){
return(
<div style={{margin:'20px'}}>我是看板</div>
)
}
export default Board
(2)App.js配置——嵌套路由
// 导入组件
import Layout from "./layout";
import Article from "./article"
import Board from "./board";
// 引入必要的内置组件
import { BrowserRouter, Routes, Route } from 'react-router-dom'
function App(){
return(
<div className="App">
<BrowserRouter>
<Routes>
<Route path="/layout" element={<Layout/>}>
{/* 二级嵌套,路由必须是一级+二级 */}
<Route path="/layout/board" element={ <Board/> } />
<Route path="/layout/article" element={ <Article/> } />
</Route>
</Routes>
</BrowserRouter>
</div>
)
}
export default App;
(3)一级路由——layout.js
import { Outlet ,Link} from 'react-router-dom'
const Layout = () => {
return (
<div style={{display:'flex'}}>
<div className='layout'>
{/* 看板跳转,路由必须是一级+二级 */}
<div style={{marginBottom:'20px'}}>
<Link to="/layout/board">看板</Link>
</div>
{/* 文章跳转*/}
<div>
<Link to="/layout/article">文章</Link>
</div>
</div>
{ /* 二级路由出口 */ }
<Outlet/>
</div>
)
}
export default Layout
2、如果要继续嵌套呢
假设文章中还要嵌套个详情页面,依葫芦画瓢啦~~~
(1)实现效果
(2)代码实现
(1)App.js
// 导入组件
import Layout from "./layout";
import Article from "./article"
import Board from "./board";
import Details from "./details";
// 引入必要的内置组件
import { BrowserRouter, Routes, Route } from 'react-router-dom'
function App(){
return(
<div className="App">
<BrowserRouter>
<Routes>
<Route path="/layout" element={<Layout/>}>
<Route path="/layout/board" element={ <Board/> } />
<Route path="/layout/article" element={ <Article/> } >
{/* 看这里,这里三级啦!!! */}
<Route path="/layout/article/details" element={ <Details/> } />
</Route>
</Route>
</Routes>
</BrowserRouter>
</div>
)
}
export default App;
(2)文章
import { Link,Outlet } from "react-router-dom"
function Article(){
return(
<div style={{marginTop:'10px',marginLeft:'30px'}}>
<div>我是文章</div>
{/* 跳转 */}
<div><Link to="/layout/article/details">点我查看详情</Link></div>
{/* 这里是路由出口,渲染渲染 */}
<Outlet/>
</div>
)
}
export default Article
3、默认路由
(1)实现步骤
- 给默认二级路由标记index属性
- 把原本的路径path属性去掉
(2)例子
假设刚刚的案例,把看板设为默认路径
<Route index element={ <Board/> } />
六、404页面配置
1、 App.js
<Route path="*" element={<NotFound />} />
<BrowserRouter>
<Routes>
<Route path="/layout" element={<Layout />}>
{/* 二级嵌套,路由必须是一级+二级 */}
<Route index element={<Board />} />
<Route path="/layout/article" element={<Article />} />
</Route>
{/* 404路由配置 */}
<Route path="*" element={<NotFound />} />
</Routes>
</BrowserRouter>
2、NotFoundjs
export function NotFound(){
return(
<div>嘿嘿,他只是走到我心里了而已</div>
)
}
3、效果
⭐七、集中式路由配置
场景: 当我们需要路由权限控制点时候, 对路由数组做一些权限的筛选过滤,所谓的集中式路由配置就是用一个数组统一把所有的路由对应关系写好替换 本来的Roues组件
// 导入组件
import { BrowserRouter, Routes, Route, useRoutes } from 'react-router-dom'
import Layout from "./layout";
import Article from "./article"
import Board from "./board";
import { NotFound } from "./NotFound";
// 1. 准备一个路由数组 数组中定义所有的路由对应关系
const routesList = [
{
path: '/layout',
element: <Layout />,
children: [
{
element: <Board />,
index: true, // index设置为true 变成默认的二级路由
},
{
path: '/layout/article',
element: <Article />,
},
],
},
// 增加n个路由对应关系
{
path: '*',
element: <NotFound />,
},
]
// 2. 使用useRoutes方法传入routesList生成Routes组件
function WrapperRoutes() {
let element = useRoutes(routesList)
return element
}
function App() {
return (
<div className="App">
<BrowserRouter>
{/* 3. 替换之前的Routes组件 */}
<WrapperRoutes />
</BrowserRouter>
</div>
)
}
export default App
实现的效果和之前的是一样的: