下午摸鱼摸久了,突然想到前端应该怎么监听路由变化,搜了一下发现这个JavaScript如何实现history路由变化监听 - 掘金 (juejin.cn),感觉两个类套来套去有点混了,仿照这个自己实现一个简易版,正好理解一下发布订阅模式
// 定义类
class HistoryListener {
public listeners: object;
constructor() {
this.listeners = {};
}
addListener(name, fn) {
const clearId = Date.now();
this.listeners[name] = this.listeners[name] ? this.listeners[name].concat[{ fn, clearId }] : [{ fn, clearId }];
return clearId;
}
notifyListener(name) {
this.listeners[name].forEach((item) => item.fn());
}
removeListener(name: string, id: number) {
const index = this.listeners[name].findIndex(item => item.clearid === id);
this.listeners[name].splice(index, 1);
}
}
const instance = new HistoryListener();
// 定义覆写history方法,在hisroty方法中插入逻辑,通知实例
const coverHistory = (name, instance) => {
const method = history[name];
return function () {
method.apply(history, arguments);
instance.notify(name);
};
}
// 覆写history方法
// 先保存一份原始方法
const ORIGIN_PUSHSTATE = history.pushState;
cosnt ORIGIN_REPLACESTATE = history.replaceState;
history.pushState = coverHistory('pushState', instance);
history.replaceState = coverHistory('replaceState', instance);
// 测试代码
const clearId1 = instance.addListener('pushState', () => {
console.log('窗口的history改变了');
});
const clearId2 = instance.addListener('pushState', () => {
console.log('窗口的history改变了-我也听到了');
});
// 移除监听
instance.removeListener('pushState', clearId1);
instance.removeListener('pushState', clearId2);
第一次发文章,怎么还没到400字,开始水了!!!
前端实现路由变化主要有两种方式,分别是通过onHashChange, 和HTML5新加的historyAPI实现URL切换无刷新功能,也是目前单页面应用实现的大部分方式
通过hash改变,利用window.onhashchange 监听。 通过history的改变,进行js操作加载页面,然而history并不像hash那样简单,因为history的改变,除了浏览器的几个前进后退(使用 history.back(), history.forward()和 history.go() 方法来完成在用户历史记录中向后和向前的跳转。)等操作会主动触发popstate 事件,pushState,replaceState 并不会触发popstate事件。
上文中实现了监听history,pushState、replaceState方法, 最后我们只需要再监听window的popstate
window.onpopstate = functino (){
console.log('popstate事件触发')
}
参考链接在这里JavaScript如何实现history路由变化监听 - 掘金 (juejin.cn),有兴趣可以对比下,希望能收到各位前辈、同仁建议,嘻嘻