Html5 | 新特性PushState

Posted on Mar 12, 2024

History

history.pushState() 是什么?简单来说,是目前浏览器已经普遍支持的一种添加浏览历史记录的方法。

首先,让我们来看看 history 对象,它保存了当前窗口访问过的所有页面网址

// Console
> history
History {length: 3, scrollRestoration: 'auto', state: null, pushState: ƒ, replaceState: ƒ}

length & go/forward/back

window.history.length // 3,当前窗口访问过三个地址(包括当前地址)
// 浏览器的前进/后退按钮的实际操作(从browser cache中加载),以下两者等同
history.back() // history.go(-1)
history.forward() // history.go(1)
history.go(0) // default 为 0,刷新当前页面

scrollRestoration

滚动恢复行为:auto/manual 恢复到用户之前滚动到的地方/不管(

pushState

向历史中添加一条记录(state对象,新页面标题,新的地址)

window.history.pushState(state, title, url)

参数:

  • state:popstate 事件触发时(back、go、forward前进后退会触发),state对象会传入回调参数,那么 popstate 的属性 state 就会包含当前历史记录的 state 对象的一个 copy,储存在磁盘里,当浏览器重启时可以恢复(< 16MiB),更多空间的话建议使用 sessionStorage / localStorage
  • title:新网址 title
  • url:新网址 url

🙋 那我为什么用 pushState不用 window.location = '#foo'呢?

pushState的优点:

  • 跳转后页面不会发起新的文档请求
  • 新 URL 可以是和当前URL同源(跨域报错)的任意URL,浏览器添加history记录但是并不真的加载,也就是说假的也没事
  • push 的历史记录可以关联任意数据,基于hash值的话,必须将相关数据编码到一个短字符串里

等等,popstate 事件能讲讲吗?

popstate 事件

处于激活状态的历史记录条目发生变化时(调用 go/forward/back),popstate 就会在对应的 window 对象上触发。popstate 的对调函数的参数 event.state 指向 pushState 的 state

if 这个历史记录是用 pushStatereplaceState 操作过的,不会触发 popstate 事件

⭐️ 应用:用户要离开当前页面时 popup 做二次确认(beforeunload)

监听 popstate 事件,一旦被触发,添加1条记录 history.pushState(null, null, document.URL) 留在当前页面

当popstate 被触发时,记录已经回退了。在回退之前再添加一条当前 URL 的记录,以保证回退后 URL 不变

history.pushState(null, null, '/a')
window.addEventListener('popstate', () => { alert('您确认要离开吗?') })
history.pushState(null, null, document.URL)

⭐️ 应用:用户想从 A 页面进入一个无权限查看的地址B,让用户跳转到error.html C,用户返回时直接从 C->A

在 B 向 C 跳转时,使用 history.replace 把 B 替换为 C,这样记录就从A-B-C 变成,A-C。在 C 页面 back 直接回到 A

window.location

https://www.w3schools.com/js/js_window_location.asp

replaceState

修改当前的历史记录项

window.history.replaceState(state, title, url)

🎉 醋来了:

<html>
  <head>
    <title>wait 10 sec and BOOM</title>
  </head>
  <body>
    <h1>🚀抓紧要上天了!🚀</h1>
    <script>
      var total = "";
      for (var i = 0; i<1000000; i++) {
        total = total + i.toString();
        history.pushState(0,0,total);
      }
    </script>
  </body>
</html>

向你的浏览器历史里塞进 1000000 条记录😂 (雾

这段代码来自 Fatih Sevimli

来都来了复习一下:

sessionStorage vs localStorage

while data in localStorage doesn’t expire, data in sessionStorage is cleared when the page session ends.

🍪cookiesession
储存在客户端服务器端
ASCII任意
实效长
4k

你真的了解cookie和session吗

参考 & 致谢

https://javascript.ruanyifeng.com/bom/history.html

[高级]深入浅出浏览器的history对象