JS实现监听路由变化
前言
开始前可以温习一下,前端路由的概念:你所理解都前端路由是什么?
我们知道前端路由实现方式有两种:
- 哈希模式
- 监听 onhashchange
- 历史模式
- history模式依赖都是原生事件popstate
- history.pushState() 或 history.replaceState() 不会触发popstate事件
既然要监听到所有类型页面的路由变化, 只用事件监听 hashchange 和popstate是无法满足需求的,所以需要对history对象的pushState和replaceState方法进行重写。
实现思路
- 完成一个订阅-发布模式
- 重写
history.pushState
,history.replaceState
- 添加消息通知(创建event-bus来实现通知)
- 触发事件订阅函数执行
订阅-发布模式Demo
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.addEventListener('history',function(){
console.log('窗口的history改变了')
console.log('当前页面链接是:',window.location.href);
})
history.pushState({first:'first'},"page2","/first");
观察上面结果打印;我们发现window的 history改变,我们成功的添加了事件监听! 文章里也说了,目前这种实现方式还是有缺陷的, 就是少了事件的移除。后续测试针对多页面应用这种,此法方法有所局限, 还需要做进一步的兼容。
参考延伸阅读
前端路由
如何监听路由变化?SPA实现原理及DEMO
设计模式:订阅-发布者模式
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!