博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JavaScript如何实现history路由变化监听
阅读量:6318 次
发布时间:2019-06-22

本文共 2913 字,大约阅读时间需要 9 分钟。

前言

大家都知道,通过浏览器的地址栏来改变切换页面,前端实现主要有两种方式:

①通过hash改变,利用window.onhashchange 监听。

②通过history的改变,进行js操作加载页面,然而history并不像hash那样简单,因为history的改变,除了浏览器的几个前进后退(使用 history.back(), history.forward()和 history.go() 方法来完成在用户历史记录中向后和向前的跳转。)等操作会主动触发popstate 事件,pushState,replaceState 并不会触发popstate事件,本篇文章主要解决history监听的问题,下面来看下具体实现

思路

我们首先完成一个订阅-发布模式,然后重写history.pushState, history.replaceState,并添加消息通知,这样一来只要history的无法实现监听函数就被我们加上了事件通知,只不过这里用的不是浏览器原生事件,而是通过我们创建的event-bus 来实现通知,然后触发事件订阅函数的执行。 废话不多说,下面我们来做具体操作。

订阅-发布模式示例

class Dep {                  // 订阅池    constructor(name){        this.id = new Date() //这里简单的运用时间戳做订阅池的ID        this.subs = []       //该事件下被订阅对象的集合    }    defined(){              // 添加订阅者        Dep.watch.add(this);    }    notify() {              //通知订阅者有变化        this.subs.forEach((e, i) => {            if(typeof e.update === 'function'){                try {                   e.update.apply(e)  //触发订阅者更新函数                } catch(err){                    console.warr(err)                }            }        })    }    }Dep.watch = null;class Watch {    constructor(name, fn){        this.name = name;       //订阅消息的名称        this.id = new Date();   //这里简单的运用时间戳做订阅者的ID        this.callBack = fn;     //订阅消息发送改变时->订阅者执行的回调函数         }    add(dep) {                  //将订阅者放入dep订阅池       dep.subs.push(this);    }    update() {                  //将订阅者更新方法        var cb = this.callBack; //赋值为了不改变函数内调用的this        cb(this.name);              }}复制代码

重写history方法,并添加window.addHistoryListener事件机制。

下面我们只需要对history的方法进行重写,并添加event-bus即可,代码如下:

var addHistoryMethod = (function(){        var historyDep = new Dep();        return function(name) {            if(name === 'historychange'){                return function(name, fn){                    var event = new Watch(name, fn)                    Dep.watch = event;                    historyDep.defined();                    Dep.watch = null;       //置空供下一个订阅者使用                }            } else if(name === 'pushState' || name === 'replaceState') {                var method = history[name];                return function(){                    method.apply(history, arguments);                    historyDep.notify();                }            }                    }}())window.addHistoryListener = addHistoryMethod('historychange');history.pushState =  addHistoryMethod('pushState');history.replaceState =  addHistoryMethod('replaceState');复制代码

测试History事件监听

上面我们给window添加了一个addHistoryListener事件监听,类似于 addEventListener的方法,然后我们有做了history的pushState, replaceState的改写,接下来我们测试一下。

window.addHistoryListener('history',function(){    console.log('窗口的history改变了');})window.addHistoryListener('history',function(){    console.log('窗口的history改变了-我也听到了');})history.pushState({
first:'first'}, "page2", "/first")复制代码

观察上面结果打印;我们发现window的 history改变,我们成功的添加了事件监听!当然这里还是有缺陷的,就是少了事件的移除,有兴趣的同学可以把接下来的移除也书写一下,熟悉熟悉。

转载于:https://juejin.im/post/5c7e2d966fb9a049bb7d131b

你可能感兴趣的文章
堆排序算法
查看>>
folders.cgi占用系统大量资源
查看>>
路由器ospf动态路由配置
查看>>
zabbix监控安装与配置
查看>>
python 异常
查看>>
last_insert_id()获取mysql最后一条记录ID
查看>>
可执行程序找不到lib库地址的处理方法
查看>>
bash数组
查看>>
Richard M. Stallman 给《自由开源软件本地化》写的前言
查看>>
oracle数据库密码过期报错
查看>>
zip
查看>>
How to recover from root.sh on 11.2 Grid Infrastructure Failed
查看>>
rhel6下安装配置Squid过程
查看>>
《树莓派开发实战(第2版)》——1.1 选择树莓派型号
查看>>
在 Linux 下使用 fdisk 扩展分区容量
查看>>
结合AlphaGo算法和大数据的量化基本面分析法探讨
查看>>
如何在 Ubuntu Linux 16.04 LTS 中使用多个连接加速 apt-get/apt
查看>>
《OpenACC并行编程实战》—— 导读
查看>>
机器学习:用初等数学解读逻辑回归
查看>>
C语言OJ项目参考(2493)四则运算
查看>>