这篇文章给大家介绍的内容是关于React Router中的核心history库的详细分析,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。
前言
使用React开发稍微复杂一点的应用,React Router几乎是路由管理的唯一选择。虽然React Router经历了4个大版本的更新,功能也越来越丰富,但无论怎么变,它的核心依赖history库却一直没变。下面我们来了解下这个在github上有4k 星的库到底提供了什么功能。
HTML5 history对象
聊到history库,是不是觉得这个单词有点熟悉?不错,HTML5规范里面,也新增了一个同名的history对象。下面我们来看下这个history对象用来解决什么问题。
在jQuery统治前端的年代,通过ajax请求无刷新更新页面是当时相当流行的页面处理方式,SPA的雏形就是那时候演化出来的。为了标示页面发生的变化,方便刷新后依然能显示正确的页面元素,一般会通过改变url的hash值来唯一定位页面。但这会带来另一个问题:用户无法使用前进/后退来切换页面。
为了解决这个问题,history对象应运而生。当页面的url或者hash发生变化的时候,浏览器会自动将新的url push到history对象中。history对象内部会维护一个state数组,记录url的变化。在浏览器进行前进/后退操作的时候,实际上就是调用history对象的对应方法(forward
/back
),取出对应的state,从而进行页面的切换。
除了操作url,history对象还提供2个不用通过操作url也能更新内部state的方法,分别是pushState
和replaceState
。还能将额外的数据存到state中,然后在onpopstate
事件中再通过event.state
取出来。如果希望对history对象作更深入的理解,可以参考 这里,和这里。
history库与HTML5 history对象的关系
我们再回过头来看history库。它本质上做了以下4件事情:
借鉴HTML5 history对象的理念,在其基础上又扩展了一些功能
提供3种类型的history:browserHistory,hashHistory,memoryHistory,并保持统一的api
支持发布/订阅功能,当history发生改变的时候,可以自动触发订阅的函数
提供跳转拦截、跳转确认和basename等实用功能
再对比一些两者api的异同。以下是history库的:
const history = { length, // 属性,history中记录的state的数量 action, // 属性,当前导航的action类型 location, // 属性,location对象,封装了pathname、search和hash等属性 push, // 方法,导航到新的路由,并记录在history中 replace, // 方法,替换掉当前记录在history中的路由信息 go, // 方法,前进或后退n个记录 goBack, // 方法,后退 goForward, // 方法,前进 canGo, // 方法,是否能前进或后退n个记录 block, // 方法,跳转前让用户确定是否要跳转 listen // 方法,订阅history变更事件 };
以下是HTML5 history对象的:
const history = { length, // 属性,history中记录的state的数量 state, // 属性,pushState和replaceState时传入的对象 back, // 方法,后退 forward, // 方法,前进 go, // 方法,前进或后退n个记录 pushState, // 方法,导航到新的路由,并记录在history中 replaceState // 方法,替换掉当前记录在history中的路由信息 } // 订阅history变更事件 window.onpopstate = function (event) { ... }
从对比中可以看出,两者的关系是非常密切的,history库可以说是history对象的超集,是功能更强大的history对象。
createHashHistory源码分析
下面,我们以三种history类型中的一种,hashHistory为例,来分析下history的源码,看看它都干了些什么。先看下它是怎么处理hash变更的。
// 构造hashHistory对象 const createHashHistory = (props = {}) => { ... const globalHistory = window.history; // 引用HTML5 history对象 ... // transitionManager负责控制是否进行跳转,以及跳转后要通知到的订阅者,后面会详细讨论 const transitionManager = createTransitionManager(); ... // 注册history变更回调的订阅者 const listen = listener => { const unlisten = transitionManager.appendListener(listener); checkDOMListeners(1); return () => { checkDOMListeners(-1); unlisten(); }; }; // 监听hashchange事件 const checkDOMListeners = delta => { listenerCount += delta; if (listenerCount === 1) { window.addEventListener(HashChangeEvent, handleHashChange); } else if (listenerCount === 0) { window.removeEventListener(HashChangeEvent, handleHashChange); } }; // hashchange事件回调 const handleHashChange = () => { ... // 构造内部使用的location对象,包含pathname、search和hash等属性 const location = getDOMLocation(); ... handlePop(location); }; // 处理hash变更逻辑 const handlePop = location => { ... const action = "POP"; // 给用户展示确认跳转的信息(如果有的话),确认后通知订阅者。如果用户取消跳转,则回退到之前状态 transitionManager.confirmTransitionTo(location, action, getUserConfirmation, ok => { if (ok) { setState({action, location}); // 确认后通知订阅者 } else { revertPop(location); // 取消则回退到之前状态 } }); }; // 更新action,location和length属性,并通知订阅者 const setState = nextState => { Object.assign(history, nextState); history.length = globalHistory.length; transitionManager.notifyListeners(history.location, history.action); }; ... }
以上就是处理被动的hash变更的逻辑,一句话概括就是:订阅hash变更事件,判断是否确实要变更,如需变更则更新自己的属性,通知订阅者,不需变更则回退到之前的状态。
下面再看下transitionManager做了什么,重点看发布/订阅相关内容,忽略用户确认跳转相关内容。
const createTransitionManager = () => { ... // 内部维护的订阅者列表 let listeners = []; // 注册订阅者 const appendListener = fn => { let isActive = true; const listener = (...args) => { if (isActive) fn(...args); }; listeners.push(listener); return () => { isActive = false; listeners = listeners.filter(item => item !== listener); }; }; //通知订阅者 const notifyListeners = (...args) => { listeners.forEach(listener => listener(...args)); }; ... }
这里的代码一目了然,就是维护一个订阅者列表,当hash变更的时候通知到相关的函数。
以上是hash改变的时候被动更新相关的内容,下面再看下主动更新相关的代码,以push
为例,replace
大同小异。
const push = (path, state) => { ... const action = "PUSH"; const location = createLocation(path, undefined, undefined, history.location); transitionManager.confirmTransitionTo(location, action, getUserConfirmation, ok => { if (!ok) // 如果取消,则不跳转 return; ... pushHashPath(encodedPath); // 用新的hash替换到url当中 ... setState({action, location}); // 更新action,location和length属性,并通知订阅者 }); }; // 用新的hash替换到url当中 const pushHashPath = path => (window.location.hash = path);
在浏览器进行前进后退操作时,history库实际上是通过操作HTML5 history对象实现的。
const globalHistory = window.history; const go = n => { ... globalHistory.go(n); }; const goBack = () => go(-1); const goForward = () => go(1);
当调用window.history.go
的时候,hash会发生变化,进而触发hashchange事件,然后history库再将变更通知到相关的订阅者。
总结
本文对React Router核心依赖history库进行了比较深入的介绍。从HTML5新增的history对象讲起,对比了它跟history库千丝万缕的关系,并以hashHistory为例子详细分析了其代码的实现细节。
最后,我们再来回顾一下history库做了哪些事情:
借鉴HTML5 history对象的理念,在其基础上又扩展了一些功能
提供3种类型的history:browserHistory,hashHistory,memoryHistory,并保持统一的api
支持发布/订阅功能,当history发生改变的时候,可以自动触发订阅的函数
提供跳转拦截、跳转确认和basename等实用功能
虽然history库是React Router的核心依赖,但它跟React本身并没有依赖关系。如果你的项目中有操作history的场景,也可以将其引入到项目中来。
相关推荐:
HTML5中标签和常用规则有哪些?html5标签以及规则的介绍
以上是React Router中的核心history库的详细分析的详细内容。更多信息请关注PHP中文网其他相关文章!

H5(HTML5)将通过新元素和API提升网页内容和设计。1)H5增强了语义化标记和多媒体支持。2)它引入了Canvas和SVG,丰富了网页设计。3)H5的工作原理是通过新标签和API扩展HTML功能。4)基本用法包括使用创建图形,高级用法涉及WebStorageAPI。5)开发者需注意浏览器兼容性和性能优化。

H5带来了多项新功能和能力,极大提升了网页的互动性和开发效率。1.语义化标签如、增强了SEO。2.多媒体支持通过和标签简化了音视频播放。3.Canvas绘图提供了动态图形绘制工具。4.本地存储通过localStorage和sessionStorage简化了数据存储。5.地理位置API便于开发基于位置的服务。

HTML5带来了五个关键改进:1.语义化标签提升了代码清晰度和SEO效果;2.多媒体支持简化了视频和音频嵌入;3.表单增强简化了验证;4.离线与本地存储提高了用户体验;5.画布与图形功能增强了网页的可视化效果。

HTML5的核心特性包括语义化标签、多媒体支持、离线存储与本地存储、表单增强。1.语义化标签如、等,提升代码可读性和SEO效果。2.和标签简化多媒体嵌入。3.离线存储和本地存储如ApplicationCache和LocalStorage,支持无网络运行和数据存储。4.表单增强引入新输入类型和验证属性,简化处理和验证。

H5提供了多种新特性和功能,极大地增强了前端开发的能力。1.多媒体支持:通过和元素嵌入媒体,无需插件。2.画布(Canvas):使用元素动态渲染2D图形和动画。3.本地存储:通过localStorage和sessionStorage实现数据持久化存储,提升用户体验。

H5和HTML5是不同的概念:HTML5是HTML的一个版本,包含新元素和API;H5是基于HTML5的移动应用开发框架。HTML5通过浏览器解析和渲染代码,H5应用则需要容器运行并通过JavaScript与原生代码交互。

HTML5的关键元素包括、、、、、等,用于构建现代网页。1.定义头部内容,2.用于导航链接,3.表示独立文章内容,4.组织页面内容,5.展示侧边栏内容,6.定义页脚,这些元素增强了网页的结构和功能性。

HTML5和H5没有区别,H5是HTML5的简称。1.HTML5是HTML的第五个版本,增强了网页的多媒体和交互功能。2.H5常用于指代基于HTML5的移动网页或应用,适用于各种移动设备。


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

SublimeText3 Linux新版
SublimeText3 Linux最新版

WebStorm Mac版
好用的JavaScript开发工具

Dreamweaver Mac版
视觉化网页开发工具

SublimeText3 英文版
推荐:为Win版本,支持代码提示!

禅工作室 13.0.1
功能强大的PHP集成开发环境