【React系列】react-router
本文来自#React系列教程:https://mp.weixin.qq.com/mp/appmsgalbum?__biz=Mzg5MDAzNzkwNA==&action=getalbum&album_id=1566025152667107329)
一. 认识react-router
1.2. 前端路由原理
前端路由是如何做到URL和内容进行映射呢?监听URL的改变。
URL 的 hash
URL的hash也就是锚点(#), 本质上是改变window.location的href属性;- 我们可以通过直接赋值
location.hash来改变href, 但是页面不发生刷新;
<div id="app"><a href="#/home">home</a><a href="#/about">about</a><div class="router-view"></div>
</div><script>// 1.获取router-viewconst routerViewEl = document.querySelector(".router-view");// 2.监听hashchangewindow.addEventListener("hashchange", () => {switch(location.hash) {case "#/home":routerViewEl.innerHTML = "home";break;case "#/about":routerViewEl.innerHTML = "about";break;default:routerViewEl.innerHTML = "default";}})
</script>
hash的优势就是兼容性更好,在老版IE中都可以运行,但是缺陷是有一个#,显得不像一个真实的路径。
HTML5 的 History
history接口是 HTML5 新增的, 它有六种模式改变URL而不刷新页面:
replaceState:替换原来的路径;pushState:使用新的路径;popState:路径的回退;go:向前或向后改变路径;forword:向前改变路径;back:向后改变路径;
我们这里来简单演示几个方法:
<div id="app"><a href="/home">home</a><a href="/about">about</a><div class="router-view"></div>
</div><script>// 1.获取router-viewconst routerViewEl = document.querySelector(".router-view");// 2.监听所有的a元素const aEls = document.getElementsByTagName("a");for (let aEl of aEls) {aEl.addEventListener("click", (e) => {e.preventDefault();const href = aEl.getAttribute("href");console.log(href);history.pushState({}, "", href);historyChange();})}// 3.监听popstate和go操作window.addEventListener("popstate", historyChange);window.addEventListener("go", historyChange);// 4.执行设置页面操作function historyChange() {switch(location.pathname) {case "/home":routerViewEl.innerHTML = "home";break;case "/about":routerViewEl.innerHTML = "about";break;default:routerViewEl.innerHTML = "default";}}</script>
1.3. react-router
目前前端流行的三大框架, 都有自己的路由实现:
- Angular的ngRouter
- React的ReactRouter
- Vue的vue-router
React Router的版本4开始,路由不再集中在一个包中进行管理了:
- react-router是router的核心部分代码;
- react-router-dom是用于浏览器的;
- react-router-native是用于原生应用的;
目前我们使用最新的React Router版本是v5的版本:
- 实际上v4的版本和v5的版本差异并不大;
安装react-router:
yarn add react-router-dom
- 安装react-router-dom会自动帮助我们安装react-router的依赖;
二. react-router基本使用
2.1. Router基本使用
react-router最主要的API是给我们提供的一些组件:
- BrowserRouter或HashRouter
- Router中包含了对路径改变的监听,并且会将相应的路径传递给子组件;
BrowserRouter使用history模式;HashRouter使用hash模式;
- Link和NavLink:
- 通常路径的跳转是使用
Link组件,最终会被渲染成a元素; NavLink是在Link基础之上增加了一些样式属性(后续学习);to属性:Link中最重要的属性,用于设置跳转到的路径;
- 通常路径的跳转是使用
- Route:
Route用于路径的匹配;path属性:用于设置匹配到的路径;component属性:设置匹配到路径后,渲染的组件;exact:精准匹配,只有精准匹配到完全一致的路径,才会渲染对应的组件;
在App中进行如下演练:
import React, { PureComponent } from 'react';import { BrowserRouter, Route, Link } from 'react-router-dom';import Home from './pages/home';
import About from './pages/about';
import Profile from './pages/profile';export default class App extends PureComponent {render() {return (<BrowserRouter><Link to="/">首页</Link><Link to="/about">关于</Link><Link to="/profile">我的</Link><Route exact path="/" component={Home} /><Route path="/about" component={About} /><Route path="/profile" component={Profile} /></BrowserRouter>)}
}

2.2. NavLink的使用
路径选中时,对应的a元素变为红色
这个时候,我们要使用NavLink组件来替代Link组件:
activeStyle:活跃时(匹配时)的样式;activeClassName:活跃时添加的class;exact:是否精准匹配;
先演示activeStyle:
<NavLink to="/" activeStyle={{color: "red"}}>首页</NavLink>
<NavLink to="/about" activeStyle={{color: "red"}}>关于</NavLink>
<NavLink to="/profile" activeStyle={{color: "red"}}>我的</NavLink>
但是,我们会发现在选中about或profile时,第一个也会变成红色:
- 原因是
/路径也匹配到了/about或/profile; - 这个时候,我们可以在第一个
NavLink中添加上exact属性;
<NavLink exact to="/" activeStyle={{color: "red"}}>首页</NavLink>
默认的activeClassName:
- 事实上在默认匹配成功时,
NavLink就会添加上一个动态的active class; - 所以我们也可以直接编写样式
a.active {color: red;
}
当然,如果你担心这个class在其他地方被使用了,出现样式的层叠,也可以自定义class
<NavLink exact to="/" activeClassName="link-active">首页</NavLink>
<NavLink to="/about" activeClassName="link-active">关于</NavLink>
<NavLink to="/profile" activeClassName="link-active">我的</NavLink>

2.3. Switch的作用
我们来看下面的路由规则:
<Route exact path="/" component={Home} />
<Route path="/about" component={About} />
<Route path="/profile" component={Profile} />
<Route path="/:userid" component={User}/>
<Route component={NoMatch}/>
- 当我们匹配到某一个路径时,我们会发现有一些问题;
- 比如
/about路径匹配到的同时,/:userid也被匹配到了,并且最后的一个NoMatch组件总是被匹配到;

原因是什么呢?默认情况下,react-router中只要是路径被匹配到的Route对应的组件都会被渲染;
但是实际开发中,我们往往希望有一种排他的思想:
- 只要匹配到了第一个,那么后面的就不应该继续匹配了;
- 这个时候我们可以使用
Switch来将所有的Route进行包裹即可;
<Switch><Route exact path="/" component={Home} /><Route path="/about" component={About} /><Route path="/profile" component={Profile} /><Route path="/:userid" component={User} /><Route component={NoMatch} />
</Switch>
2.3. Redirect的使用
Redirect用于路由的重定向,当这个组件出现时,就会执行跳转到对应的to路径中:
我们这里使用这个的一个案例:
- 用户跳转到
User界面; - 但是在
User界面有一个isLogin用于记录用户是否登录:true:那么显示用户的名称;false:直接重定向到登录界面;
App.js中提前定义好Login页面对应的Route:
<Switch>...其他Route<Route path="/login" component={Login} /><Route component={NoMatch} />
</Switch>
在User.js中写上对应的逻辑代码:
import React, { PureComponent } from 'react'
import { Redirect } from 'react-router-dom';export default class User extends PureComponent {constructor(props) {super(props);this.state = {isLogin: false}}render() {return this.state.isLogin ? (<div><h2>User</h2><h2>用户名: coderwhy</h2></div>): <Redirect to="/login"/>}
}
三. react-router高级使用
3.1. 路由嵌套
在开发中,路由之间是存在嵌套关系的。
这里我们假设about页面中有两个页面内容:
- 商品列表和消息列表;
- 点击不同的链接可以跳转到不同的地方,显示不同的内容;
import React, { PureComponent } from 'react';import { Route, Switch, Link } from 'react-router-dom';function AboutProduct(props) {return (<ul><li>商品列表1</li><li>商品列表2</li><li>商品列表3</li></ul>)
}function AboutMessage(props) {return (<ul><li>消息列表1</li><li>消息列表2</li><li>消息列表3</li></ul>)
}export default class About extends PureComponent {render() {return (<div><Link to="/about">商品</Link><Link to="/about/message">消息</Link><Switch><Route exact path="/about" component={AboutProduct} /><Route path="/about/message" component={AboutMessage} /></Switch></div>)}
}
3.2. 手动跳转
目前我们实现的跳转主要是通过Link或者NavLink进行跳转的,实际上我们也可以通过JavaScript代码进行跳转。
但是通过JavaScript代码进行跳转有一个前提:必须获取到history对象。
如何可以获取到history的对象呢?两种方式
- 方式一:如果该组件是通过路由直接跳转过来的,那么可以直接获取
history、location、match对象; - 方式二:如果该组件是一个普通渲染的组件,那么不可以直接获取
history、location、match对象;
那么如果普通的组件也希望获取对应的对象属性应该怎么做呢?
- 前面我们学习过高阶组件,可以在组件中添加想要的属性;
react-router也是通过高阶组件为我们的组件添加相关的属性的;
如果我们希望在App组件中获取到history对象,必须满足以下两个条件:
App组件必须包裹在Router组件之内;App组件使用withRouter高阶组件包裹;
index.js代码修改如下:
ReactDOM.render(<BrowserRouter><App /></BrowserRouter>,document.getElementById('root')
);
App.js代码修改如下:
import { Route, Switch, NavLink, withRouter } from 'react-router-dom';
...省略其他的导入代码class App extends PureComponent {render() {console.log(this.props.history);return (<div>...其他代码<button onClick={e => this.pushToProfile()}>我的</button><Switch><Route exact path="/" component={Home} /><Route path="/about" component={About} /><Route path="/profile" component={Profile} /><Route path="/:userid" component={User} /><Route component={NoMatch} /></Switch></div>)}pushToProfile() {this.props.history.push("/profile");}
}export default withRouter(App);
源码选读:这里的 history 来自哪里呢?是否和之前使用的 window.history 一样呢?
我们发现withRouter的高阶函数来自react-router-dom:
实际上来自react-router的包;

withRouter函数:

history对象来自哪里呢?
- 实际来自上面代码的
context;

这个context的值来自哪里呢?
- 来自于
context.Consumer的value中;

this.props.history来自哪里呢?
- 来自
BrowserRouter或者HashRouter在创建时,传入的值; - 又传递给了
Router,Router的子组件可以通过该context获取到这个值;

createBrowserHistory来自哪里呢?

执行push操作的本质:

3.3 传递参数
传递参数有三种方式:
- 动态路由的方式;
search传递参数;to传入对象;
动态路由的方式
动态路由的概念指的是路由中的路径并不会固定:
- 比如
/detail的path对应一个组件Detail; - 如果我们将
path在Route匹配时写成/detail/:id,那么/detail/abc、/detail/123都可以匹配到该Route,并且进行显示; - 这个匹配规则,我们就称之为动态路由;
通常情况下,使用动态路由可以为路由传递参数。
<div>...其他Link<NavLink to="/detail/abc123">详情</NavLink><Switch>... 其他Route<Route path="/detail/:id" component={Detail}/><Route component={NoMatch} /></Switch>
</div>
detail.js的代码如下:
import React, { PureComponent } from 'react'export default class Detail extends PureComponent {render() {console.log(this.props.match.params.id);return (<div><h2>Detail: {this.props.match.params.id}</h2></div>)}
}
- 我们可以直接通过
match对象中获取id; - 这里我们没有使用
withRouter,原因是因为Detail本身就是通过路由进行的跳转;
search传递参数
NavLink写法:
<NavLink to="/detail2?name=why&age=18">详情2</NavLink><Switch><Route path="/detail2" component={Detail2}/>
</Switch>
- 我们在跳转的路径中添加了一些
query参数;
Detail2中如何获取呢?
Detail2中是需要在location中获取search的;- 注意:这个
search没有被解析,需要我们自己来解析;
import React, { PureComponent } from 'react'export default class Detail2 extends PureComponent {render() {console.log(this.props.location.search); // ?name=why&age=18return (<div><h2>Detail2:</h2></div>)}
}
to传入对象
to可以直接传入一个对象
<NavLink to={{pathname: "/detail2", query: {name: "kobe", age: 30},state: {height: 1.98, address: "洛杉矶"},search: "?apikey=123"}}>详情2
</NavLink>
获取参数:
import React, { PureComponent } from 'react'export default class Detail2 extends PureComponent {render() {console.log(this.props.location);return (<div><h2>Detail2:</h2></div>)}
}

补充:使用 history.push 如何传递参数
在React中如何使用history.push传递参数主要有三种方式:
第一种如下:
this.props.history.push{pathname:'/router/url/send',query:{'oneFlag':one,}}
接收情况如下:
this.props.location.query.oneFlag
其路由路径显示:
'#/router/url/send?oneFlag=one'
第二种情况如下:
this.props.history.push{pathname:'/router/url/send',state:{'oneFlag':one,}
}
接收情况如下:
this.props.location.state.oneFlag // one
其路由显示:
'#/router/url/send'
第三种情况需要在配置路由时,将路由配置为rest格式路由,
{path: '/device/detail/:id',component: DeviceDetail,pageConfig: {title: '设备详情',auth: ['admin'],},},
传递参数时:
<Button text type="primary" onClick={() => history.push({ pathname: `/device/detail/${record.id}` })}>详情
</Button>
参数接收时:
const { id } = props.match.params;
第一种和第三种,在目标路由刷新后,参数还可以取到,但是第二种页面刷新后,参数就取不到了,第二种适合开发winform类的应用。
第一种和三种在使用时要注意监听参数的变化,不然路由回退,再次进图另外参数的页面,组件不会重新渲染,用hook组件开发的话,需要用useEffect来监听参数变化。
四. react-router-config
目前我们所有的路由定义都是直接使用Route组件,并且添加属性来完成的。
但是这样的方式会让路由变得非常混乱,我们希望将所有的路由配置放到一个地方进行集中管理:
- 这个时候可以使用
react-router-config来完成;
安装react-router-config:
yarn add react-router-config
常见router/index.js文件:
import Home from "../pages/home";
import About, { AboutMessage, AboutProduct } from "../pages/about";
import Profile from "../pages/profile";
import Login from "../pages/login";
import User from "../pages/user";
import Detail from "../pages/detail";
import Detail2 from "../pages/detail2";
import NoMatch from "../pages/nomatch";const routes = [{path: "/",exact: true,component: Home},{path: "/about",component: About,routes: [{path: "/about",exact: true,component: AboutProduct},{path: "/about/message",component: AboutMessage},]},{path: "/profile",component: Profile},{path: "/login",component: Login},{path: "/user",component: User},{path: "/detail/:id",component: Detail},{path: "/detail2",component: Detail2},{component: NoMatch}
];export default routes;
将之前的Switch配置,换成react-router-config中提供的renderRoutes函数:
{renderRoutes(routes)}{/* <Switch><Route exact path="/" component={Home} /><Route path="/about" component={About} /><Route path="/profile" component={Profile} /><Route path="/user" component={User} /><Route path="/login" component={Login} /><Route path="/detail/:id" component={Detail}/><Route path="/detail2" component={Detail2}/><Route component={NoMatch} /></Switch> */}
如果是子组件中,需要路由跳转,那么需要在子组件中使用renderRoutes函数:
- 在跳转到的路由组件中会多一个
this.props.route属性; - 该
route属性代表当前跳转到的路由对象,可以通过该属性获取到routes;
export default class About extends PureComponent {render() {return (<div><Link to="/about">商品</Link><Link to="/about/message">消息</Link>{renderRoutes(this.props.route.routes)}</div>)}
}
实际上react-router-config中还提供了一个matchRoutes辅助函数:
matchRoutes(routes, pathname)传入一个路由对象数组,获取所有匹配的路径;
const routes = matchRoutes(this.props.route.routes, "/about");
console.log(routes);
查看renderRoutes的源码也是非常简单的:

相关文章:
【React系列】react-router
本文来自#React系列教程:https://mp.weixin.qq.com/mp/appmsgalbum?__bizMzg5MDAzNzkwNA&actiongetalbum&album_id1566025152667107329) 一. 认识react-router 1.2. 前端路由原理 前端路由是如何做到URL和内容进行映射呢?监听URL的改变。 UR…...
[数据集][目标检测]车辆检测数据集VOC+YOLO格式1.6w张3类别
一共分为3个压缩包: 【车辆检测数据集AVOCYOLO格式5423张3类别】 数据集格式:Pascal VOC格式YOLO格式(不包含分割路径的txt文件,仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数):5423 标注数…...
FindMy技术用于鼠标
鼠标是计算机的标准配置之一,其设计初衷是为了使计算机的操作更加简便快捷,减少用户在操作中的负担。用户可以通过移动鼠标,实现光标的精确移动,进而选择、拖拽、复制、粘贴等操作。这种操作方式,使得计算机的操作变得…...
已解决‘ping‘ 不是内部或外部命令,也不是可运行的程序或批处理文件。”的问题
已解决‘ping‘ 不是内部或外部命令,也不是可运行的程序或批处理文件。”的问题 文章目录 问题介绍 问题分析 解决思路 解决方法 检查并修复环境变量 进入c:\windows\system32再ping 使用系统工具修复系统文件 Q1 - 问题介绍 当您尝试在Windows命令提示符下…...
基于PGPGPOOL-II部署PostgreSQL高可用环境
PGPOOL-II是一个位于PostgreSQL服务器和 PostgreSQL 数据库客户端之间的中间件,具有以下功能: 1. 连接池:PGPOOL-II可以保持已经连接到 PostgreSQL 服务器的连接,并在使用相同参数(例如:用户名、数据库、协议版本)连接进来时重用它们。这可以减少连接开销,并增加系统的…...
【大数据进阶第二阶段之Hadoop学习笔记】Hadoop 运行环境搭建
【大数据进阶第二阶段之Hadoop学习笔记】Hadoop 概述-CSDN博客 【大数据进阶第二阶段之Hadoop学习笔记】Hadoop 运行环境搭建-CSDN博客 【大数据进阶第二阶段之Hadoop学习笔记】Hadoop 运行模式-CSDN博客 1、模板虚拟机环境准备 1.1、 hadoop100 虚拟机配置要求如下 &…...
Python 操作 JMeter 探索:pymeter 实操指南
概要 JMeter 是一个流行的性能测试工具,用于测试 Web 应用程序的性能和负载。它通常与 GUI 一起使用,但如果您想在自动化测试中集成 JMeter,或者以编程方式创建和运行测试计划,那么 pymeter 库将是一个强大的工具。本文将介绍如何…...
微软 Power Platform 使用Power Automate发送邮件以Dataverse作为数据源的附件File Column
微软Power Platform使用Power Automate发送邮件添加Power Apps以Dataverse作为数据源的附件File Column方式 目录 微软Power Platform使用Power Automate发送邮件添加Power Apps以Dataverse作为数据源的附件File Column方式1、需求背景介绍2、附件列File Column介绍3、如何在Po…...
雾天条件下 SLS 融合网络的三维目标检测
论文地址:3D Object Detection with SLS-Fusion Network in Foggy Weather Conditions 论文代码:https://github.com/maiminh1996/SLS-Fusion 论文摘要 摄像头或激光雷达(光检测和测距)等传感器的作用对于自动驾驶汽车的环境意识…...
在pycharm中执行 os.makedirs 提示用户名或密码不正确
问题:在pycharm中运行脚本,在 \10.0.21.249\share 共享目录下创建目录提示错误 发现:手动在该目录下创建目录没有问题。 解决方法: 切换到cmd 命令行运行该脚本成功创建 猜测:感觉应该是pycharm中使用的用户名和密码存…...
使用Go语言编写高效的HTTP服务器
随着互联网的快速发展,HTTP服务器在Web开发中扮演着越来越重要的角色。而Go语言作为一种高效、并发性强的编程语言,为编写高性能的HTTP服务器提供了强大的支持。本文将探讨如何使用Go语言编写高效的HTTP服务器。 首先,我们需要了解Go语言的H…...
代码随想录day20 开始二叉搜索树
654.最大二叉树 题目 给定一个不含重复元素的整数数组。一个以此数组构建的最大二叉树定义如下: 二叉树的根是数组中的最大元素。左子树是通过数组中最大值左边部分构造出的最大二叉树。右子树是通过数组中最大值右边部分构造出的最大二叉树。 通过给定的数组构…...
从0开始python学习-39.requsts库
目录 HTTP协议 1. 请求 2. 响应 Requests库 1. 安装 2. 请求方式 2.1 requests.请求方式(参数) 2.2 requests.request() 2.3 requests.session().request() 2.4 三种方式之间的关联 3. 请求参数 3.1 params:查询字符串参数 3.2 data:Form表单…...
【面试高频算法解析】算法练习3 双指针
前言 本专栏旨在通过分类学习算法,使您能够牢固掌握不同算法的理论要点。通过策略性地练习精选的经典题目,帮助您深度理解每种算法,避免出现刷了很多算法题,还是一知半解的状态 专栏导航 二分查找回溯双指针滑动窗口深度优先搜索…...
React16源码: Why16, 研究源码的意义, 源码目录核心结构分析
为什么要选择React16 现在React18都早已实践很多,为何回过头来看16版本的代码理由如下 从实际出发,企业内老旧项目多为16版本,理解16的核心能够帮助我们快速解决问题16版本React是完全重写了核心代码, 是一次重大的更新 引入了 fiber 这个概…...
mybatis-flex笔记
MyBatis-Flex 的增删改功能 - MyBatis-Flex 官方网站https://mybatis-flex.com/zh/base/add-delete-update.html 代码https://gitee.com/hntianshu/mybatis-flex-test 一 新增数据 不忽略 null 值。 就是允许有null 忽略null 就是不允许有null BaseMapper 的接口提供了 inser…...
Debezium发布历史47
原文地址: https://debezium.io/blog/2019/02/13/debezium-0-9-1-final-released/ 欢迎关注留言,我是收集整理小能手,工具翻译,仅供参考,笔芯笔芯. Debezium 0.9.1.Final 发布 二月 13, 2019 作者: Gunna…...
Python爬虫抓包常见问题解决
对于Python爬虫和Fiddler抓包,可能遇到的问题及解决: 代理设置错误:如果你在使用Python爬虫时遇到抓不到包的问题,首先应该检查你的浏览器代理设置是否正确。以Chrome为例,代理设置为:右上角菜单按钮>设…...
c++跨平台ui
fltk https://gitee.com/mirrors_fltk/fltk.git codeblock中有fltk项目开发模板,可以快速构建项目 wxwidget https://gitee.com/sofu456/wxWidgets.git git submodule update --init --recursive 打开demo和sample set(wxBUILD_SAMPLES ALL) set(wxBUILD_DEMOS ON) build/…...
stable diffusion 基础教程-提示词之艺术风格用法
展现夕阳 golden hour, (rim lighting):1.2, warm tones, sun flare, soft shadows, vibrant colors, hazy glow, painterly effect, dreamy atmosphere阴影 chiaroscuro, (high contrast):1.2, dramatic shadows, bold highlights, moody atmosphere, captivating inte…...
【网络】每天掌握一个Linux命令 - iftop
在Linux系统中,iftop是网络管理的得力助手,能实时监控网络流量、连接情况等,帮助排查网络异常。接下来从多方面详细介绍它。 目录 【网络】每天掌握一个Linux命令 - iftop工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景…...
【OSG学习笔记】Day 18: 碰撞检测与物理交互
物理引擎(Physics Engine) 物理引擎 是一种通过计算机模拟物理规律(如力学、碰撞、重力、流体动力学等)的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互,广泛应用于 游戏开发、动画制作、虚…...
条件运算符
C中的三目运算符(也称条件运算符,英文:ternary operator)是一种简洁的条件选择语句,语法如下: 条件表达式 ? 表达式1 : 表达式2• 如果“条件表达式”为true,则整个表达式的结果为“表达式1”…...
微信小程序 - 手机震动
一、界面 <button type"primary" bindtap"shortVibrate">短震动</button> <button type"primary" bindtap"longVibrate">长震动</button> 二、js逻辑代码 注:文档 https://developers.weixin.qq…...
SAP学习笔记 - 开发26 - 前端Fiori开发 OData V2 和 V4 的差异 (Deepseek整理)
上一章用到了V2 的概念,其实 Fiori当中还有 V4,咱们这一章来总结一下 V2 和 V4。 SAP学习笔记 - 开发25 - 前端Fiori开发 Remote OData Service(使用远端Odata服务),代理中间件(ui5-middleware-simpleproxy)-CSDN博客…...
CSS | transition 和 transform的用处和区别
省流总结: transform用于变换/变形,transition是动画控制器 transform 用来对元素进行变形,常见的操作如下,它是立即生效的样式变形属性。 旋转 rotate(角度deg)、平移 translateX(像素px)、缩放 scale(倍数)、倾斜 skewX(角度…...
基于Springboot+Vue的办公管理系统
角色: 管理员、员工 技术: 后端: SpringBoot, Vue2, MySQL, Mybatis-Plus 前端: Vue2, Element-UI, Axios, Echarts, Vue-Router 核心功能: 该办公管理系统是一个综合性的企业内部管理平台,旨在提升企业运营效率和员工管理水…...
STM32---外部32.768K晶振(LSE)无法起振问题
晶振是否起振主要就检查两个1、晶振与MCU是否兼容;2、晶振的负载电容是否匹配 目录 一、判断晶振与MCU是否兼容 二、判断负载电容是否匹配 1. 晶振负载电容(CL)与匹配电容(CL1、CL2)的关系 2. 如何选择 CL1 和 CL…...
实战设计模式之模板方法模式
概述 模板方法模式定义了一个操作中的算法骨架,并将某些步骤延迟到子类中实现。模板方法使得子类可以在不改变算法结构的前提下,重新定义算法中的某些步骤。简单来说,就是在一个方法中定义了要执行的步骤顺序或算法框架,但允许子类…...
归并排序:分治思想的高效排序
目录 基本原理 流程图解 实现方法 递归实现 非递归实现 演示过程 时间复杂度 基本原理 归并排序(Merge Sort)是一种基于分治思想的排序算法,由约翰冯诺伊曼在1945年提出。其核心思想包括: 分割(Divide):将待排序数组递归地分成两个子…...
