前戏
Window.history是一个只读属性,用来获取History 对象的引用,History 对象提供了操作浏览器会话历史的接口,使用 back(), forward() 和 go() 方法来完成在用户历史记录中向后和向前的跳转。
主角登场
HTML5引入了 history.pushState() 和 history.replaceState() 方法,它们分别可以添加和修改历史记录条目。这些方法通常与window.onpopstate 配合使用
/**
* stateObj 状态对象,可以用作传输数据
* title 标题,当前浏览器均不支持
* url 访问地址,新URL必须与当前URL同源
*/
history.pushState(stateObj, title, url);
history.replaceState(stateObj, title, url);
复制代码
使用场景
实现返回拦截(用户在访问页面的时候,执行了浏览器的返回操作,而又不想让用户立即退出的情况下)
举个例子:当用户访问a.html,点击返回,拦截到b.html
const updateUserHistory = (url) => {
// 保存当前访问地址
const currentUrl = window.location.href
// 修改当前历史记录
window.history.replaceState({ isReload: false }, '', url)
// 添加新的历史记录
window.history.pushState({ isReload: false }, '', currentUrl)
}
updateUserHistory('b.html')
// 监听浏览器历史记录发生改变时
window.addEventListener('popstate', function(e) {
if (!e.state.isReload) {
const state = e.state
state.isReload = true
// 历史记录发生改变,页面内容并未改变,通过刷新才能更新内容
window.location.reload()
}
}, false)
复制代码
前端路由之History实现(其实hash也能实现)
举个例子:点击导航页面内容发生改变而不刷新,即达到单页面的效果
// 路由发生改变
const pushState = (url) => {
window.history.pushState({}, '', url);
// 更新页面操作
};
// 监听用户前进后退
window.addEventListener('popstate', function(e) {
// 更新页面操作
}, false);
// 路由
const routers = [
'entry.html?page=1',
'entry.html?page=2',
'entry.html?page=3'
];
// 点击导航操作
$('.link').on('click', (e) => {
const index = e.target.dataset.index;
pushState(routers[index]);
});
复制代码
在路由发生变化或用户前进后退时,根据当前路由,决定页面显示的那天【更新页面操作】。当然上面的实现只是核心,很多细节并未考虑进去。比如页面之间传参,其实可以通过stateObj对象进行传递。