CSS/HTML

推荐列表 站点导航

当前位置:首页 > 脚本编程 > CSS/HTML >

React Router中的核心history库的详细分析

来源:网络整理  作者:  发布时间:2020-12-22 05:13
这篇文章给大家介绍的内容是关于React Router中的核心history库的详细分析,有一定的参考价值,有需要的朋友可以参考...

使用h5实现react拖拽排序组件的方法(附代码)

下面再看下transitionManager做了什么,重点看发布/订阅相关内容,忽略用户确认跳转相关内容。

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对象的:

支持发布/订阅功能,当history发生改变的时候,可以自动触发订阅的函数

相关推荐:

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变更的时候通知到相关的函数。

这篇文章给大家介绍的内容是关于React Router中的核心history库的详细分析,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。

前言

使用React开发稍微复杂一点的应用,React Router几乎是路由管理的唯一选择。虽然React Router经历了4个大版本的更新,功能也越来越丰富,但无论怎么变,它的核心依赖history库却一直没变。下面我们来了解下这个在github上有4k+星的库到底提供了什么功能。

提供3种类型的history:browserHistory,hashHistory,memoryHistory,并保持统一的api

createHashHistory源码分析

下面,我们以三种history类型中的一种,hashHistory为例,来分析下history的源码,看看它都干了些什么。先看下它是怎么处理hash变更的。

提供跳转拦截、跳转确认和basename等实用功能

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对象实现的。

HTML5 history对象

聊到history库,是不是觉得这个单词有点熟悉?不错,HTML5规范里面,也新增了一个同名的history对象。下面我们来看下这个history对象用来解决什么问题。

为了解决这个问题,history对象应运而生。当页面的url或者hash发生变化的时候,浏览器会自动将新的url push到history对象中。history对象内部会维护一个state数组,记录url的变化。在浏览器进行前进/后退操作的时候,实际上就是调用history对象的对应方法(forward/back),取出对应的state,从而进行页面的切换。

以上是hash改变的时候被动更新相关的内容,下面再看下主动更新相关的代码,以push为例,replace大同小异。

history库与HTML5 history对象的关系

我们再回过头来看history库。它本质上做了以下4件事情:

除了操作url,history对象还提供2个不用通过操作url也能更新内部state的方法,分别是pushState和replaceState。还能将额外的数据存到state中,然后在onpopstate事件中再通过event.state取出来。如果希望对history对象作更深入的理解,可以参考 这里,和这里。

在jQuery统治前端的年代,通过ajax请求无刷新更新页面是当时相当流行的页面处理方式,SPA的雏形就是那时候演化出来的。为了标示页面发生的变化,方便刷新后依然能显示正确的页面元素,一般会通过改变url的hash值来唯一定位页面。但这会带来另一个问题:用户无法使用前进/后退来切换页面。

HTML5如何解决margin-top的塌陷问题(附代码)

// 构造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变更事件,判断是否确实要变更,如需变更则更新自己的属性,通知订阅者,不需变更则回退到之前的状态。

提供跳转拦截、跳转确认和basename等实用功能

HTML5中标签和常用规则有哪些?html5标签以及规则的介绍

以上就是React Router中的核心history库的详细分析的详细内容,更多请关注聚合云库其它相关文章!

支持发布/订阅功能,当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对象。

再对比一些两者api的异同。以下是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库再将变更通知到相关的订阅者。

提供3种类型的history:browserHistory,hashHistory,memoryHistory,并保持统一的api

借鉴HTML5 history对象的理念,在其基础上又扩展了一些功能

虽然history库是React Router的核心依赖,但它跟React本身并没有依赖关系。如果你的项目中有操作history的场景,也可以将其引入到项目中来。

最后,我们再来回顾一下history库做了哪些事情:

借鉴HTML5 history对象的理念,在其基础上又扩展了一些功能

总结

本文对React Router核心依赖history库进行了比较深入的介绍。从HTML5新增的history对象讲起,对比了它跟history库千丝万缕的关系,并以hashHistory为例子详细分析了其代码的实现细节。

相关热词:

本站内容来源于网络,如有侵权请与我们联系,我们会及时删除,我们深感抱歉!
注:本站所有信息仅供用于网络技术学习参考,学习中请遵循相关法律法规!

本文地址: https://v30.fanwenzhu.com/jiaob/cssm/6969.shtml

相关文章
Copyright © www.juheyunku.com      关于 | 合作 | 声明 | 联系 | 更新 | 地图 | Tags

React Router中的核心history库的详细分析

2020-12-22 编辑:

使用h5实现react拖拽排序组件的方法(附代码)

下面再看下transitionManager做了什么,重点看发布/订阅相关内容,忽略用户确认跳转相关内容。

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对象的:

支持发布/订阅功能,当history发生改变的时候,可以自动触发订阅的函数

相关推荐:

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变更的时候通知到相关的函数。

这篇文章给大家介绍的内容是关于React Router中的核心history库的详细分析,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。

前言

使用React开发稍微复杂一点的应用,React Router几乎是路由管理的唯一选择。虽然React Router经历了4个大版本的更新,功能也越来越丰富,但无论怎么变,它的核心依赖history库却一直没变。下面我们来了解下这个在github上有4k+星的库到底提供了什么功能。

提供3种类型的history:browserHistory,hashHistory,memoryHistory,并保持统一的api

createHashHistory源码分析

下面,我们以三种history类型中的一种,hashHistory为例,来分析下history的源码,看看它都干了些什么。先看下它是怎么处理hash变更的。

提供跳转拦截、跳转确认和basename等实用功能

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对象实现的。

HTML5 history对象

聊到history库,是不是觉得这个单词有点熟悉?不错,HTML5规范里面,也新增了一个同名的history对象。下面我们来看下这个history对象用来解决什么问题。

为了解决这个问题,history对象应运而生。当页面的url或者hash发生变化的时候,浏览器会自动将新的url push到history对象中。history对象内部会维护一个state数组,记录url的变化。在浏览器进行前进/后退操作的时候,实际上就是调用history对象的对应方法(forward/back),取出对应的state,从而进行页面的切换。

以上是hash改变的时候被动更新相关的内容,下面再看下主动更新相关的代码,以push为例,replace大同小异。

history库与HTML5 history对象的关系

我们再回过头来看history库。它本质上做了以下4件事情:

除了操作url,history对象还提供2个不用通过操作url也能更新内部state的方法,分别是pushState和replaceState。还能将额外的数据存到state中,然后在onpopstate事件中再通过event.state取出来。如果希望对history对象作更深入的理解,可以参考 这里,和这里。

在jQuery统治前端的年代,通过ajax请求无刷新更新页面是当时相当流行的页面处理方式,SPA的雏形就是那时候演化出来的。为了标示页面发生的变化,方便刷新后依然能显示正确的页面元素,一般会通过改变url的hash值来唯一定位页面。但这会带来另一个问题:用户无法使用前进/后退来切换页面。

HTML5如何解决margin-top的塌陷问题(附代码)

// 构造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变更事件,判断是否确实要变更,如需变更则更新自己的属性,通知订阅者,不需变更则回退到之前的状态。

提供跳转拦截、跳转确认和basename等实用功能

HTML5中标签和常用规则有哪些?html5标签以及规则的介绍

以上就是React Router中的核心history库的详细分析的详细内容,更多请关注聚合云库其它相关文章!

支持发布/订阅功能,当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对象。

再对比一些两者api的异同。以下是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库再将变更通知到相关的订阅者。

提供3种类型的history:browserHistory,hashHistory,memoryHistory,并保持统一的api

借鉴HTML5 history对象的理念,在其基础上又扩展了一些功能

虽然history库是React Router的核心依赖,但它跟React本身并没有依赖关系。如果你的项目中有操作history的场景,也可以将其引入到项目中来。

最后,我们再来回顾一下history库做了哪些事情:

借鉴HTML5 history对象的理念,在其基础上又扩展了一些功能

总结

本文对React Router核心依赖history库进行了比较深入的介绍。从HTML5新增的history对象讲起,对比了它跟history库千丝万缕的关系,并以hashHistory为例子详细分析了其代码的实现细节。

本站内容来源于网络,如有侵权请与我们联系,我们会及时删除,我们深感抱歉!
注:本站所有信息仅供学习参考!
本文地址为 https://v30.fanwenzhu.com/jiaob/cssm/6969.shtml

相关文章

风云图片

推荐阅读

返回CSS/HTML频道首页