-
web端使用路由安装的是
react-router-dom"react-router-dom": "^5.2.0"
-
在组件中使用路由,我们先设置2个路由,分别是首页、关于
// src/components/RouteSample.js
import React from 'react';
// 引入路由需要的基础模块
import {BrowserRouter, Link, Route} from 'react-router-dom'export default function RouteSample () {
return (
{/* 导航链接 */} <div><Link to="/">首页</Link></div> <div><Link to="/about">关于</Link></div> {/* 路由配置:路由就是组件 */} <Route path="/" component={Home}></Route> <Route path="/about" component={About}></Route> </div> </BrowserRouter> </div> )}
然后补充首页、关于2个组件,这时页面就可以切换路由了,但是发现一个问题,当路由切换至
about时,首页的内容依然展示在页面上,这是react一个特点叫包容式路由,默认情况是多个组件组成一个页面展示,也就是当我们访问/about时会包含/的内容
"关于"页面.jpg// src/components/RouteSample.js
function Home() {
return
Home
}function About () {
return (
About
)
}接着上面的情况想要改成独占式的路由,也就是一个路由只展示当前组件,我们用到一个属性
exact{/* 路由配置:路由就是组件 */}
react路由也是有动态路由概念的,我们在首页展示一个课程列表,点击分别进入对应的课程详情页,继续在上面的代码基础上扩展// src/components/RouteSample.js
function Home() {
return
Home
- web
- ios
}// src/components/RouteSample.js
{/* 新增详情页路由 lesson就是动态传参的部分*/}
// src/components/RouteSample.js
// 新增详情页组件
// 传递进来的是路由器对象
// 路由器对象主要包含以下3部分,可以结合下面的具体截图理解
// 1. history 导航指令 history.goBack
// 2. match 获取参数信息
// 3. location 当前url信息
function Detail (routeParams) {
console.log('routeParams',routeParams)
return (
当前课程:{routeParams.match.params.lesson}
)
}路由器参数.jpg
-
在开发过程中有时候会碰到所有路由都不匹配的情况,也就是路径不对、页面找不到,通常会给一个404页面,在
react中这样处理,加上404路由之后会发现无论路由在哪个页面404页面会一直显示(如下图),这里又遇到上面同样的问题react路由匹配时包容性质的,这里用到一个新组件Switch,不用像之前给每个组件添加exact属性那么麻烦,路由只会在Switch包裹范围内选1个,修改完之后会发现只有在路由都不匹配的情况下才会显示404页面// src/components/RouteSample.js
// 新增404页面组件 展示访问的具体路径不存在
function NoMatch ({location}) {
return (
404, {location.pathname}不存在
)
}// 新增404路由
{/* 404页面没有path 当有path的路由都不匹配时那必然匹配404*/}
首页展示404.jpg
ios详情页显示404.jpg
// src/components/RouteSample.js import React from 'react'; // 引入Switch import {BrowserRouter, Link, Route, Switch} from 'react-router-dom' {/* 路由配置:路由就是组件 */} {/* 用Switch包裹路由配置,避免展示包容式路由 */} <Switch> <Route exact path="/" component={Home}></Route> <Route path="/about" component={About}></Route> <Route path="/detail/:lesson" component={Detail}></Route> {/* 404页面没有path 当有path的路由都不匹配时那必然匹配404*/} <Route component={NoMatch}></Route> </Switch>路由不存在显示404.jpg
-
接着再研究下路由嵌套,修改一下
About组件,用作展示当前用户信息,分为"个人信息"和"订单信息",按原先的路由结构来看,现在"个人信息"、"订单信息"就是嵌套在About下的,从页面上可以看出这里有一个问题,就是点击"关于"展示About时,没有给嵌套路由默认展示项,必须要手动再次点击"个人信息"或者"订单信息"才能正常显示(默认情况如下图),这时候可以给一个路由重定向作为默认展示的路由,结合vue还是很容易理解的// src/components/RouteSample.js
// 当前用户信息
function About () {
return (
About
个人信息
订单信息
<Route path="/about/me" component={() => (me)}>
<Route path="/about/order" component={() => (order)}>
)
}
about默认不展示嵌套路由内容.jpg
// src/components/RouteSample.js import {BrowserRouter, Link, Route, Switch, Redirect} from 'react-router-dom' <Switch> <Route path="/about/me" component={() => (<div>me</div>)}></Route> <Route path="/about/order" component={() => (<div>order</div>)}></Route> {/* 路由默认项 */} <Redirect to="/about/me"></Redirect> </Switch>-
路由中有一项非常重要的功能是路由守卫,可以用于很多场景,最常见的就是以是否登录判断显示当前访问页面还是跳转登录页,
react中的路由守卫跟vue-router的有很大不同,react是用一个高阶组件扩展<Route>// src/components/RouteSample.js
// 保留路由组件所需的参数component、以及其他参数例如pth等,同时传一个登录状态isLogin
function PrivateRoute ({component: Comp, isLogin, ...rest}) {
return (
// render函数 根据条件动态渲染组件
// 未登录则重定向至登录页
// 登录路由也配置了一个redirect,这样在设计登录组件的时候当登录成功即重定向跳转至登录前访问的页面
<Route
{...rest}
render = {
props => isLogin ? () : (<Redirect
to={{pathname: "/login", state: {redirect: props.location.pathname}}}
>)
}
>
)
} -
然后补充登录组件和路由配置,同时修改
About组件的使用// src/components/RouteSample.js
// 从路由参数拿到重定向地址,从redux获取登录状态和登录方法
function Login ({location, isLogin, login}) {
const redirect = location.state.redirect || '/'
if(isLogin) {
return
}
return (
用户登录
)
}{/* 路由配置:路由就是组件 /}
使用路由守卫 /}
{/
{/ 404页面没有path 当有path的路由都不匹配时那必然匹配404*/}
-
上一步已经实现了路由守卫的逻辑,下一步则补充
redux中关于登录状态以及登录方法异步请求的相关内容,新建redux中的用户模块,路径是src/store/user.redux.js,用户模块添加完成后要在src/store/index.js中完成注册才能使用// src/store/user.redux.js
// 初始化状态,没在登录中 并且 未登录
const initial = {
isLogin: false,
loading: false
}export const user = (state = initial, action) => {
switch(action.type) {
// 登录中
case "requestLogin":
return {
isLogin: false,
loading: true
};
// 已登录
case "login":
return {
isLogin: true,
loading: false
};
default:
return state;
}
}// 请求登录异步调用时,先修改状态为登录中
export const login = () => dispatch => {
dispatch({type: 'requestLogin'});
setTimeout(() => {
dispatch({type: 'login'})
}, 1500);
}// src/store/index.js
// applyMiddleware 应用中间件方法
import {createStore, applyMiddleware, combineReducers} from 'redux';
import logger from 'redux-logger'
import thunk from 'redux-thunk'
import {user} from './user.redux'const store = createStore(
combineReducers({user}),
applyMiddleware(logger, thunk)
);export default store;
-
完成以上模块添加之后再回到路由守卫的部分做对应修改,路由守卫和登录组件都需要用到登录状态值,这里我们使用
react-redux// src/components/RouteSample.js
// 添加引用
import {connect} from 'react-redux';
import {login} from '../store/user.redux'// 路由守卫
const PrivateRoute = connect(
state => ({isLogin: state.user.isLogin})
)(
({component: Comp, isLogin, ...rest}) => {
return (
// render 根据条件动态渲染组件
<Route
{...rest}
render={
props => isLogin ?
() :
(<Redirect
to={{pathname: "/login", state: {redirect: props.location.pathname}}}
>)
}
>
)
}
)// 登录组件
const Login = connect(
// 映射状态与dispatch方法
state => ({
isLogin: state.user.isLogin,
loading: state.user.loading
}),
{login}
)(
({location, isLogin, login, loading}) => {
const redirect = location.state.redirect || '/'
if(isLogin) {
return
}
return (
用户登录
{/* loading优化 */}
)
}
) -
最后需要注意的是使用路由组件时使用方式、引入
store的方式// App.js
import store from './store/index'
import {Provider} from 'react-redux'import RouteSample from './components/RouteSample'
{/* router */}
-
下图展示了整个登录流程发生的记录
登录流程.jpg
© 著作权归作者所有,转载或内容合作请联系作者
喜欢的朋友记得点赞、收藏、关注哦!!!
React - router的使用 && 结合react-redux的路由守卫
荆州克莱2025-01-13 17:00
相关推荐
Flittly1 小时前
【AgentScope Java新手村系列】(14)人机交互吃饱了得干活17 小时前
Spring Cloud Gateway 微服务网关:路由、断言、过滤器Flynt20 小时前
从Spring Boot 4.0升到4.1,我在Maven和gRPC上栽了跟头掉鱼的猫2 天前
Spring Boot → Solon 注解迁移实战指南:一张对照表说清楚人活一口气3 天前
Spring Boot与AIGC的完美结合:从零搭建智能内容生成平台唐青枫4 天前
Java Spring WebFlux 实战指南:用 Mono、Flux 和 WebClient 写响应式接口咖啡八杯5 天前
GoF设计模式——策略模式java小白小6 天前
SpringBoot(01): 初识SpringBoot,从Spring的痛点说起用户3169353811836 天前
如何从零编写一个 Spring Boot Starter程序员晓琪7 天前
约定大于配置:基于 Java 包名自动生成 API 版本路由的最佳实践热门推荐
012026年6月AI大模型全景报告:GPT-5.6、Claude Opus 4.8、Gemini 3.5,中美AI三足鼎立谁主沉浮?022026年6月AI行业全景:从百模大战到Agent元年,这30天发生了什么?032026 年 AI 编程工具终极横评:Cursor vs Claude Code vs Copilot vs Windsurf04飞书长连接_事件订阅(接收消息,审批任务状态变更)05Trae国际版与国内版深度测评:AI原生IDE的双生花06【AI】2026 年具身智能模型和世界模型总结07GitHub 镜像站点08Claude Code、Codex、Cursor三分天下:2026年AI编程Agent生态全景剖析092026 AI 编程工具终极实战指南:Cursor vs Claude Code vs Copilot,开发者该怎么选?102026年AI架构实战:彻底解决OpenAI接口超时与封号,Python调用GPT-5.2/Sora2企业级架构详解(附源码+压测报告)