- 初阶:
- hash:
http://example.com/#abc/bbc
- 使用
window.onhashchange
监听变更事件,做出反应;直接修改页面hash,改变路由位置 - 不会带到服务端,无法做SSR
- 不利于做 seo;失去原生页面锚点定位能力
- 兼容IE8
- 不需要兼容处理
- 使用
- history:
[http://example.com/abc/bbc](http://example.com/#abc/bbc)
- 使用 HTML5 History Interface 的
popState
监听路由变化;使用 pushState()和replaceState()方法 - history 对服务端来说与普通url一致,可以做 ssr,容易做seo优化
- history 可以携带 state 对象,hash只能带字符串
- 兼容 IE10
- 需要服务端做兼容处理
- 使用 HTML5 History Interface 的
- hash:
中阶:
history 依赖
popstate
事件监听路由变化,但 pushState、replaceState 都不会触发这个事件,所以:- 监听所有 a 路由的click事件,拦截,调用 pushState 更改路由
- 拦截 history 原生 pushState、replaceState 方法,为它们添加事件特性
const listener = function (type) {
var orig = history[type];
return function () {
var rv = orig.apply(this, arguments);
var e = new Event(type);
e.arguments = arguments;
window.dispatchEvent(e);
return rv;
};
};
window.history.pushState = listener('pushState');
window.history.replaceState = listener('replaceState');
hashchange 事件只有在hash变化的时候才会触发,所以初始化时还需要额外监听 load 事件
// replaceState和pushState行为的监听
initHistoryHook(cb: Function){
let history:any = window.history
let bindHistoryEventListener = function(type: string){
let originEvent = history[type]
console.log('arguments', arguments, this)
return function(){
let newEvent = originEvent.apply(this, arguments)
// 事件发生时就会触发这个回调
cb(type, arguments)
return newEvent
}
}
history.pushState = bindHistoryEventListener('pushState')
history.replaceState = bindHistoryEventListener('replaceState')
}