当前位置: 首页 > news >正文

react-router/react-router-dom

最近看了react-router 源码,对react-router有了更深的理解,下面写点东西备忘:
react-router-dom 是对react-router 的扩展,而两者实现路由跳转的本质依赖于一个history 插件。
此history 插件 是对浏览器原生 history 的封装。

BrowserHistory

1.push

 function push(path, state) {
...globalHistory.pushState({key: key,state: state}, null, href);
...
}

2.replace

function replace(path, state) {
...globalHistory.replaceState({key: key,state: state}, null, href);
...
}

3.Listeners

var PopStateEvent = 'popstate';
var HashChangeEvent = 'hashchange';
function checkDOMListeners(delta) {listenerCount += delta;if (listenerCount === 1 && delta === 1) {window.addEventListener(PopStateEvent, handlePopState);if (needsHashChangeListener) window.addEventListener(HashChangeEvent, handleHashChange);} else if (listenerCount === 0) {window.removeEventListener(PopStateEvent, handlePopState);if (needsHashChangeListener) window.removeEventListener(HashChangeEvent, handleHashChange);}}

总结 :history router 基于 html5 新增的 history API,pushState, replaceState,其用法如下:
history.pushState(state, title, url);
history.replaceState(state, title, url);
即:跳转到 url 路径(与当前页面处在同一个域 ,形如一个网站的
location.pathname 部分),指定新页面的标题 title,但是浏览器目前都忽略这个值,因此这里一般使用 null,state 为关联新地址的状态对象(刷新页面并不会丢失)。二者的区别就是,pushState 会增加一条浏览器记录,而replaceState 会替换当前历史记录。相同点是,均不会刷新当前页面,也不会发生真正的跳转,而是仅仅改变了地址栏的 URL(history、location 对象)。
同时 history router 通过 popstate 来监听变化。

hash router

1.push

function pushHashPath(path) {window.location.hash = path;
}
  1. replace
function replaceHashPath(path) {window.location.replace(stripHash(window.location.href) + '#' + path);
}
  1. Listeners
var HashChangeEvent$1 = 'hashchange';
function checkDOMListeners(delta) {listenerCount += delta;if (listenerCount === 1 && delta === 1) {window.addEventListener(HashChangeEvent$1, handleHashChange);} else if (listenerCount === 0) {window.removeEventListener(HashChangeEvent$1, handleHashChange);}}

总结: hash router 基于 location.hash = pathString 来更新网站路径。pathString 代表网址中 # 号后面直到 search 的部分。与 history 不同的是,如果两次赋值一样的时候,并不会触发 hashchange 和 popstate 方法。同时浏览器通过 hashchange 事件来监听路由变化。

MemoryHistory

在非浏览器环境,使用抽象路由实现导航的记录功能MemoryHistory,即在内存中保存的一个创建的虚拟路由对象。

getUserConfirmation

getUserConfirmation 约等于 vue-router 中路由守卫,它是在路由跳转时的钩子函数,当传入它时可以在getUserConfirmation 内控制时都进行路由跳转。
getUserConfirmation 的用法如下

<BrowserRoutergetUserConfirmation={(message, callback) => {// this is the default behaviorconst allowTransition = window.confirm(message);callback(allowTransition);}}
/>

即 当callback(true) 会跳转,callback(false) 不会跳转,那么我们看一下 在触发路由跳转时 做了什么操作

 function confirmTransitionTo(location, action, getUserConfirmation, callback) {// TODO: If another transition starts while we're still confirming// the previous one, we may end up in a weird state. Figure out the// best way to handle this.if (prompt != null) {var result = typeof prompt === 'function' ? prompt(location, action) : prompt;if (typeof result === 'string') {if (typeof getUserConfirmation === 'function') {getUserConfirmation(result, callback);     // 重点在这里} else {warning(false, 'A history needs a getUserConfirmation function in order to use a prompt message');callback(true);}} else {// Return false from a transition hook to cancel the transition.callback(result !== false);}} else {callback(true);}}

在进行跳转时会调用getUserConfirmation 传入result, callback
callback 什么函数呢? 以createBrowserHistory push 中的为例:

 function push(path, state) {warning(!(typeof path === 'object' && path.state !== undefined && state !== undefined), 'You should avoid providing a 2nd state argument to push when the 1st ' + 'argument is a location-like object that already has state; it is ignored');var action = 'PUSH';var location = createLocation(path, state, createKey(), history.location);transitionManager.confirmTransitionTo(location, action, getUserConfirmation, function (ok) {if (!ok) return;  // 传入非 true 则不进行任何操作var href = createHref(location);var key = location.key,state = location.state;if (canUseHistory) {globalHistory.pushState({key: key,state: state}, null, href);if (forceRefresh) {window.location.href = href;} else {var prevIndex = allKeys.indexOf(history.location.key);var nextKeys = allKeys.slice(0, prevIndex + 1);nextKeys.push(location.key);allKeys = nextKeys;setState({action: action,location: location});}} else {warning(state === undefined, 'Browser history cannot push state in browsers that do not support HTML5 history');window.location.href = href;}});}

可见 callback 中只有传入true 才可以执行下一步,由此我们可以通过 getUserConfirmation 实现路由拦截。

最后编辑于:2025-06-15 11:02:55


喜欢的朋友记得点赞、收藏、关注哦!!!

http://www.lryc.cn/news/613498.html

相关文章:

  • 深度学习中主要库的使用:(一)pandas,读取 excel 文件,支持主流的 .xlsx/.xls 格式
  • 房产证识别在房产行业的技术实现及应用原理
  • 超高车辆如何影响城市立交隧道安全?预警系统如何应对?
  • 网络基础概念
  • 基于Qt的Live2D模型显示以及控制
  • ora-01658 无法为表空间 users中的段创建initial区
  • RocketMQ架构解析
  • 遥感卫星领域的AI应用
  • Day03 学习git
  • LWIP网络接口管理
  • [airplay2] airplay2简略介绍
  • 二分查找算法,并分析其时间、空间复杂度
  • IIS7.5下的https无法绑定主机头,显示灰色如何处理?
  • 前后端加密传数据实现方案
  • [ java SE ] 多人聊天窗口1.0
  • 强光干扰下裂缝漏检率↓82%!陌讯轻量化模型在道路巡检的落地实践
  • redis--黑马点评--用户签到模块详解
  • JAVA,Maven继承
  • 力扣经典算法篇-46-阶乘后的零(正向步长遍历,逆向步长遍历)
  • Linux Shell为文件添加BOM并自动转换为unix格式
  • 数据分析——Pandas库
  • 什么是 TDengine IDMP?
  • 机试备考笔记 7/31
  • 学习设计模式《二十一》——装饰模式
  • 人生后半场:从广度到深度的精进之路
  • 设计模式中的行为模式
  • 多线程 future.get()的线程阻塞是什么意思?
  • tcpdump问题记录
  • 【多重BFS】Monsters
  • 【实时Linux实战系列】基于实时Linux的高频交易系统构建