目录
一、介绍
现代的前端应用大多数是SPA(单页应用程序),也就是只有一个HTML页面的应用程序。因为它的用户体验更好、对服务器压力更小,所以更受欢迎。为了有效的使用单个页面来管理多页面的功能,前端路由应运而生。
Ø 前端路由功能:让用户从一个视图(组件)导航到另一个视图(组件)
Ø 前端路由是一套映射规则,在React中,是URL路径与组件的对应关系
Ø 使用React路由简单来说,就是配置路径和组件
注意:2021年11月路由依赖包react-router-dom开启v6版本,注意新api的变化
在介绍完v5.0稳定版以后,会在文章后面介绍v6.0版本的改动以及案例演示。
二、事前准备
2.1 安装路由模块
2.2 相关组件
三、V5版本路由使用
3.1 声明式导航
使用Link或NavLink组件完成声明式导航的定义
代码展示:
import React, { Component } from 'react';
// 引入相关组件
import { Link,Route,Switch,NavLink } from 'react-router-dom'
// 引入类组件
import Home from './pages/Home';
import User from './pages/User';
class App extends Component {
render() {
return (
<>
{/* 声明式导航 */}
< NavLink to={"/home"} >home页面</NavLink>
< NavLink to={"/user"}>user页面</NavLink>
<Switch>
<Route path={"/home"} component = { Home }></Route>
<Route path={"/user"} component = { User }></Route>
</Switch>
</>
);
}
}
export default App;
运行结果:
3.2 编程式导航
通过与react-router-dom中withRouter与history对象中的push/replace/go等方法搭配使用实现编程式导航功能。
这里需要注意,引入whitRouter,用于解决this.props.history 拿不到值的问题。
import React, { Component } from 'react';
// 引入相关组件
import { Link,Route,Switch,NavLink } from 'react-router-dom'
// 引入类组件
import Home from './pages/Home';
import User from './pages/User';
// 引入withRouter来解决 this.props.history 拿不到值的问题
import { withRouter } from 'react-router-dom'
@withRouter
class App extends Component {
homeHander = () =>{
console.log(this.props.history);
this.props.history.push("/home")
}
userHander = () =>{
console.log(this.props.history);
this.props.history.push("/user")
}
render() {
return (
<>
{/* 编程式导航 */}
<a onClick={this.homeHander}>home界面</a>
<a onClick={this.userHander}>user界面</a>
<Switch>
<Route path={"/home"} component = { Home }></Route>
<Route path={"/user"} component = { User }></Route>
</Switch>
</>
);
}
}
export default App;
3.3 嵌套路由
3.4 路由传参
3.4.1 动态路由参数(param)
通过this.props.match.params拿值
运行结果:
3.4.2 查询字符串(query)
通过 this.props.location.search 拿值
运行结果:
3.4.3 隐式传参(state)
这里注意,传过去的参数刷新会消失
通过this.props.location.state拿state的值
通过this.props.history.location.params拿params的值
运行结果:
3.5 重定向 与 404
3.6 三种路由的渲染方式【了解】
3.6.1 component= (组件对象或者函数)
3.6.2 render 函数
3.6.3 children(函数或者组件)
3.6.4 3种渲染区别总结
-
component可以使用组件类渲染或内联式方式渲染,render只能使用函数,children使用函数或直接使用组件对象
-
component内联式渲染方式在每次匹配路由成功后都将创建一个新组件,而后两者不会,所以用内联式方式建议使用后两者,内联方式渲染组件,推荐用render
-
当children的值是一个函数时,无论当前地址和path路径匹不匹配,都将会执行children对应的函数,当children的值为一个组件时,当前地址和path不匹配时,路由组件不渲染
-
children函数方式渲染,会在形参中接受到一个对象,对象中match属性如果当前地址匹配成功返回对象,否则null
3.7 withRouter高阶组件
import {
useLocation,
useNavigate,
useParams
} from "react-router-dom";
// useNavigate 用来跳转用的 函数组件使用 useLocation接收参数用 useParams接收参数
export function withRouter(Component) {
function ComponentWithRouterProp(props) {
let location = useLocation();
let navigate = useNavigate();
let params = useParams();
return (
<Component
{...props}
router={{ location, navigate, params }}
/>
);
}
return ComponentWithRouterProp;
}
3.8 自定义导航组件
import React, { Component } from 'react';
// 引入相关组件
import { Link,Route,Switch,NavLink } from 'react-router-dom'
// 引入函数组件
import Home from './pages/Home';
import User from './pages/User';
// 引入自定义导航组件
import Mylink from './pages/Mylink';
class App extends Component {
render() {
return (
<>
{/* 传参 */}
< NavLink to="/home" >home页面</NavLink>
< NavLink to="/user">user页面</NavLink>
{/* 引入自定义导航组件 */}
<Mylink to="/home" tag = 'p'>首页</Mylink>
<Mylink to="/user"tag = 'p'>用户页</Mylink>
<Switch>
<Route path="/user" component = { Home }></Route>
<Route path="/user" component = { User }></Route>
</Switch>
</>
);
}
}
export default App;
自定义路由组件 公共组件
import React from 'react';
import { Route , withRouter } from 'react-router-dom'
const Mylink = (props) => {
const handerClick = () => {
props.history.push(props.to)
}
const Tag = props.tag
const to = props.to
return (
// match 使用函数组件 类组件match获取不到最新匹配的值
<Route path={to} children={({match})=>{
console.log('match',match);
if(match){
return <Tag style={{color:'red'}} onClick={ handerClick }
>{ props.children }</Tag>
}
return <Tag onClick={handerClick}
>{ props.children }</Tag>
}} />
);
}
export default withRouter(Mylink);
运行结果:
四、V6版本路由使用
4.1 声明式导航
三个改动:
-
swicth替换为 Routes
-
comopnent替换为 element
-
element里以前是直接放User 现在是<User/>
import React, { Component } from 'react';
import { Route, Routes, Link, useNavigate } from 'react-router-dom'
import User from './pages/User';
import Home from './pages/Home';
class App extends Component {
render() {
return (
<>
{/* swicth替换为 Routes */}
<Routes>
{/* comopnent替换为 element */}
<Route path='/home' element={<Home />}></Route>
{/* 以前是直接放User 现在是<User/> */}
<Route path='/user' element={<User />}></Route>
</Routes>
<Link to={'/home'}>首页</Link>
<Link to={'/user'}>用户</Link>
</>
);
}
}
export default App;
4.2 编程式导航
通过this.props.router.navigate进行路径更改
需要注意的是V6版本中,删除了withRouter,所以需要自己封装,并引入
WithRouter代码如下:
import {
useLocation,
useNavigate,
useParams
} from "react-router-dom";
// useNavigate 用来跳转用的 函数组件使用 useLocation接收参数用 useParams接收参数
export function withRouter(Component) {
function ComponentWithRouterProp(props) {
let location = useLocation();
let navigate = useNavigate();
let params = useParams();
return (
<Component
{...props}
router={{ location, navigate, params }}
/>
);
}
return ComponentWithRouterProp;
}
代码展示:
import React, { Component } from 'react';
import { Route, Routes, Link, useNavigate } from 'react-router-dom'
import User from './pages/User';
import Home from './pages/Home';
// 需要自己封装 V6版本删除了withRouter
import {withRouter} from './pages/WithRouter';
class App extends Component {
hander = ()=>{
console.log(this.props);
this.props.router.navigate('/home')
}
handers = ()=>{
console.log(this.props);
this.props.router.navigate('/user')
}
render() {
return (
<>
{/* swicth替换为 Routes */}
<Routes>
{/* comopnent替换为 element */}
<Route path='/home' element={<Home />}></Route>
{/* 以前是直接放User 现在是<User/> */}
<Route path='/user' element={<User />}></Route>
</Routes>
<Link to={'/home'}>首页</Link>
<Link to={'/user'}>用户</Link>
{/* 编程式导航 */}
<button onClick={this.hander}>首页</button>
<button onClick={this.handers}>用户</button>
</>
);
}
}
export default withRouter(App);
运行结果:
4.3 重定向与404
4.3.1 重定向
先引入navigate
import { Route, Routes, Link, useNavigate,Navigate } from 'react-router-dom'
使用
<Route index element={ <Navigate to="/home "/>}/>
4.3.2 404
<Route path= "*" element={ <NotFind />} />
4.4 传参
4.4.1 query传参
this.props.router.location.search 接收参数
this.props.router.navigate('/home?name=xzl')
4.4.2 params传参
this.props.router.params 接收参数
this.props.router.navigate('/user/12345') 传参
<Route path='/user/:id' element={<User />}></Route> 路由更改
4.4.3 state传参
注意:V6中state传参只能用于函数组件,类组件不可用
先引入
import { useLocation } from 'react-router-dom'
再赋值
var localtion = useLocation()
最后通过 localtion.state 接收参数。
4.5 嵌套路由
方法一:
<Routes>
{/* 注意带*号表示下面有路由匹配 */}
<Route path='/home/*' element={<Home />}>
{/* 二级路由不带 / */}
<Route path='Footer' element={<Footer />}></Route>
<Route path='Header' element={<Header />}></Route>
</Route>
<Route path='/user' element={<User />}></Route>
</Routes>
注意这里需要在二级路由页面有类似于vue路由占位符一样的东西。
方法二:
4.6 批量配置路由
import React from 'react'
import { useRoutes } from 'react-router-dom'
import Home from './pages/Home'
import User from './pages/User'
import NotFind from './pages/NotFind'
import MyHeader from './pages/MyHeader'
import MyFooter from './pages/MyFooter'
export default function App() {
//useRoutes //use开头的函数 统称hooks 函数组件专用 v6常用编程了函数组件
var ele = useRoutes([
{
path:'/home',
element: <Home />,
children:[
{path:'myheader',element: <MyHeader /> },
{path:'myfooter',element: <MyFooter /> },
]
},
{ path:'/user',element: <User />},
{ path:'*',element: <NotFind />},
])
return (
<div>
<h3>useRoutes案例</h3>
{ ele }
</div>
)
}