深入理解React Router:从原理到实践
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

2.3.3 history监听

hashHistory的监听函数listen接口与browserHistory的接口完全一致:

当location记录发生变化时,会触发listen监听的回调函数。回调函数参数列表中第一个参数location为变化后的地址信息;第二个参数action为跳转类型,分别为“POP”“PUSH”“REPLACE”。

history的设计风格都是在调用订阅函数之后返回一个取消订阅的函数,可调用取消订阅函数取消history的监听:

类似于addEventListener可对单个事件添加多个回调函数,history.listen同样可多次调用,添加多个监听函数:

对于多次调用监听函数,也会返回响应的注销方法,可分别调用注销方法取消history的监听。

对于history.listen,类似于浏览器的事件订阅,当监听到location变化时,会通知监听函数。在history.listen的源码实现上,调用history.listen将事件回调函数保存到一个监听列表中。监听列表维护了一个回调函数数组,当需要取消响应事件时,则将需要取消的回调函数从这个回调函数数组中移除。当需要通知事件时,对回调函数数组中的每一个函数依次进行调用。其源码如下:

在上例源码中,listen将通过checkDOMListeners(1)监听原生的浏览器事件,如popstate事件,参数中的数字表示listen的调用计数。调用一次listen,内存中变量会加1;当移除事件时,内存中变量会减1。只有当值为0时,调用checkDOMListeners(1)才会注册一次相关原生事件,这样避免了调用listen多次注册浏览器事件。