pushState 和 replaceState
HTML5新接口,可以改变网址(存在跨域限制)而不跳转页面,这个强大的特性后来用到了单页面应用如:vue-router,react-router-dom 中。
注意:vue-router 的 hash 模式是用的onhashchange
,与此功能无关。
window.history.pushState(state, title, targetURL);
@状态对象:传给目标路由的信息,可为空
@页面标题:目前所有浏览器都不支持,填空字符串即可
@可选url:目标url,不会检查url是否存在,且不能跨域。如不传该项,即给当前url添加data
window.history.replaceState(state, title, targetURL);
@类似于pushState,但是会直接替换掉当前url,而不会在history中留下记录
popstate事件
popstate
事件会在点击后退、前进按钮(或调用history.back()
、history.forward()
、history.go()
方法)时触发。前提是不能真的发生了页面跳转,而是在由history.pushState()
或者history.replaceState()
形成的历史节点中前进后退
注意:直接调用history.pushState()
或者history.replaceState()
不会触发popstate
事件。
window.onpopstate = function(event) {
console.log(event.state);
console.log(window.history.state);
};
以上两种方式皆可获取之前在pushState
和replaceState
中传入的state
监听pushState和replaceState
由于history.pushState()
或者history.replaceState()
不会触发popstate
,需要自己定义事件以进行监听。
- 重写pushState,先驱动自定义回调函数/事件,再调用原生的pushState
(function (history) {
var pushState = history.pushState;
history.pushState = function (state) {
if (typeof history.onpushstate == "function") {
history.onpushstate({ state: state });
}
return pushState.apply(history, arguments);
};
})(window.history);
history.onpushstate = function (e) {
console.log('pushed', e);//e即state
}
const state = { 'page_id': 1 }
const title = ''
const url = 'hello.html'
history.pushState(state, title, url);
var _wr = function(type) {
var orig = history[type];
return function() {
var e = new Event(type);
e.arguments = arguments;
window.dispatchEvent(e);
var rv = orig.apply(this, arguments);
return rv;
};
};
history.pushState = _wr('pushState');
history.replaceState = _wr('replaceState');
window.addEventListener('pushState', function(e) {
var path = e && e.arguments.length > 2 && e.arguments[2];
var url = /^http/.test(path) ? path : (location.protocol + '//' + location.host + path);
console.log('old:'+location.href,'new:'+url);
});
window.addEventListener('replaceState', function(e) {
var path = e && e.arguments.length > 2 && e.arguments[2];
var url = /^http/.test(path) ? path : (location.protocol + '//' + location.host + path);
console.log('old:'+location.href,'new:'+url);
});