pushState 和 replaceState
HTML5新接口,可以改變網(wǎng)址(存在跨域限制)而不跳轉(zhuǎn)頁(yè)面痊硕,這個(gè)強(qiáng)大的特性后來(lái)用到了單頁(yè)面應(yīng)用如:vue-router赊级,react-router-dom 中。
注意:vue-router 的 hash 模式是用的onhashchange
岔绸,與此功能無(wú)關(guān)。
window.history.pushState(state, title, targetURL);
@狀態(tài)對(duì)象:傳給目標(biāo)路由的信息,可為空
@頁(yè)面標(biāo)題:目前所有瀏覽器都不支持,填空字符串即可
@可選url:目標(biāo)url橡伞,不會(huì)檢查url是否存在盒揉,且不能跨域。如不傳該項(xiàng),即給當(dāng)前url添加data
window.history.replaceState(state, title, targetURL);
@類似于pushState,但是會(huì)直接替換掉當(dāng)前url,而不會(huì)在history中留下記錄
popstate事件
popstate
事件會(huì)在點(diǎn)擊后退兑徘、前進(jìn)按鈕(或調(diào)用history.back()
刚盈、history.forward()
、history.go()
方法)時(shí)觸發(fā)挂脑。前提是不能真的發(fā)生了頁(yè)面跳轉(zhuǎn),而是在由history.pushState()
或者history.replaceState()
形成的歷史節(jié)點(diǎn)中前進(jìn)后退
注意:直接調(diào)用history.pushState()
或者history.replaceState()
不會(huì)觸發(fā)popstate
事件藕漱。
window.onpopstate = function(event) {
console.log(event.state);
console.log(window.history.state);
};
以上兩種方式皆可獲取之前在pushState
和replaceState
中傳入的state
監(jiān)聽(tīng)pushState和replaceState
由于history.pushState()
或者history.replaceState()
不會(huì)觸發(fā)popstate
,需要自己定義事件以進(jìn)行監(jiān)聽(tīng)崭闲。
- 重寫pushState肋联,先驅(qū)動(dòng)自定義回調(diào)函數(shù)/事件,再調(diào)用原生的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);
});