JS之BOM篇history对象

history对象保存了用户从打开窗口那一刻的上网历史记录。出于安全限制,开发人员无法读取用户的历史记录,但是可以通过history提供的方法,在不知道实际URL的情况下实现后退和前进

属性

history.length表示历史记录的URL数量,初始值是1,如果已经访问了3个网址,history.length值就是3

console.log(history.length); // 1

方法

history对象提供了go()、back()、forward()方法,用于操作浏览历史之间的移动

go()

go()方法可以在历史记录中任意跳转,它接收一个整数值作为参数,表示向前或向后的页面数。负数表示向后跳转(类似于后退按钮),正数表示向前跳转(类似于前进按钮),0相当于刷新当前页面

history.go(-1); // 后退一步
history.go(2); // 前进两步
history.go(0); // 刷新当前页

back()

back()方法用于模仿浏览器的后退按钮,相当于history.go(-1)

history.back();

forward()

forward()方法用于模仿浏览器的前进按钮,相当于history.go(1)

history.forward();

注意: 如果移动的位置超出了访问历史的边界,以上三个方法并不报错,而是静默失败。使用历史记录时,页面通常从浏览器缓存之中加载,而不是重新要求服务器发送新的网页

增改记录

HTML5为history对象提供了history.pushState()history.replaceState()方法,用于添加和修改浏览器历史记录。

pushState()

pushState()方法接收三个参数:状态对象stateObject、标题title、URL地址(可选)。该方法向历史记录中添加一个状态

状态对象:状态对象是一个由pushState()方法创建、与历史记录相关的JavaScript对象。当用户定向到一个新状态时会触发popstate事件,该事件有一个state属性,包含了历史记录的state对象。如果不需要状态对象,可以填null

标题:新页面的标题,但是所有浏览器目前都忽略这个值,因此可以填null

URL地址:新历史记录的地址。新URL必须和当前URL在同一个域,否则会报错。该参数是可选的,如果没有提供会被设置为当前文档的URL

history.pushState(state, title, url);
<button id="btn">添加记录</button>
<script>
  var stateObj = {posts: 'b'};
  btn.onclick = function() {
    history.pushState(stateObj, '文章标题', 'b.html')
  }
</script>

假设现在的地址是http://127.0.0.1:3030/a.html,点击添加记录按钮后,地址会变成http://127.0.0.1:3030/b.html。添加历史记录不会刷新页面,仅仅是视觉上的URL改变,所以点击浏览器的前进和后退按钮,始终显示的是a.html的内容

注意: 如果URL参数设置了一个新的锚点值,不会触发hashchange事件

<button id="btn">添加记录</button>
<script>
  var stateObj = {posts: 'b'};
  btn.onclick = function() {
    history.pushState(stateObj, null, '#b')
  }
  window.onhashchange = function(e) {
    console.log('hash change')
  }
</script>

当地址从http://127.0.0.1:3030/#a变成http://127.0.0.1:3030/#b,控制台不会打印hash change

但是下面这种hash变化,是可以监听到的

<body>
  <a href="#a">aaa</a>
  <a href="#b">bbb</a>

  <div id="a"></div>
  <div id="b"></div>
  <script>
    window.onhashchange = function () {
      console.log(111);
    }
  </script>
</body>

replaceState()

history.replaceState()方法的参数与pushState()一样,不同之处在于replaceState()方法会修改当前历史记录条目而并非创建新的条目

<button id="btn">添加记录1</button>
<button id="btn2">添加记录2</button>
<button id="btn3">替换记录2</button>
<script>
  btn.onclick = function() {
    history.pushState({posts: 'a'}, null, 'a.html')
  }
  btn2.onclick = function() {
    history.pushState({posts: 'b'}, null, 'b.html')
  }
  btn3.onclick = function() {
    history.replaceState({posts: 'c'}, null, 'c.html')
  }
</script>

依次点击上面三个按钮,URL变化依次是http://127.0.0.1:3030 => http://127.0.0.1:3030/a.html => http://127.0.0.1:3030/b.html => http://127.0.0.1:3030/c.html。现在点击后退按钮,会跳转到a.html;点击前进按钮,会跳转到c.html。由于b.html被替换掉了,所以不会再出现

state

history.state属性返回当前页面的state对象

btn.onclick = function() {
  history.pushState({posts: 'a'}, null, 'a.html')
  console.log(history.state) // {posts: "a"}
}

popstate事件

当history对象发生变化时,会触发popstate事件。需要注意的是,只有当用户点击了浏览器的返回和前进按钮,或者使用history的back()、forward()、go()方法时才会触发该事件。仅仅调用pushState方法或replaceState方法,并不会触发该事件。另外,该事件只针对同一文档的切换才有效,如果历史记录的切换导致加载不同的文档,不会触发该事件

<button id="btn">添加记录</button>
<button id="btn2">back</button>
<button id="btn3">forward</button>
<script>
  btn.onclick = function() {
    history.pushState({posts: 'a'}, null, 'a.html')
  }
  btn2.onclick = function() {
    history.go(-1)
  }
  btn3.onclick = function() {
    history.go(1)
  }
  window.onpopstate = function(e) {
    console.log(e.type, e.state)
  }
</script>

添加记录后,点击back返回popstate null,点击forward返回popstate {posts: "a"}

往返缓存

浏览器有一个特性叫“往返缓存”(back-forward cache或bfcache),可以在用户使用浏览器的“后退”和“前进”按钮时加快页面的转换速度。这个缓存中不仅保存着页面数据,还保存了DOM和javascript的状态;实际上是将整个页面都保存在了内存里。如果页面位于bfcache中,那么再次打开该页面时就不会触发load事件

注意: IE10-浏览器不支持

pageshow

pageshow事件在页面加载时触发,包括第一次加载和从缓存中加载两种情况。如果要指定网页每次加载时都运行的代码,可以放在这个事件的监听函数里

第一次加载时,它的触发顺序排在load事件后面。从缓存加载时,load事件不会触发,pageshow事件会触发

pageshow事件有一个persisted属性,返回一个布尔值。页面没有从缓存加载时,这个属性是false;当页面从缓存加载时,这个属性是true

注意: 必须将其事件处理程序添加到window对象

window.addEventListener('load', function(e) {
  console.log('loaded')
})
window.addEventListener('pageshow', function(e) {
  console.log(e.persisted)
})
// 'loaded'
// false

pagehide

pagehide事件会在浏览器卸载页面的时候触发,它会在unload事件之前触发

注意: 必须将其事件处理程序添加到window对象

注意: 指定了unload事件处理程序的页面不会从缓存中加载,即使事件处理程序是空的,原因在于unload常用于撤销load中的初始化操作,跳过onload后再次显示页面很可能就会导致页面不正常

pagehide事件的event对象也包含persisted属性,如果页面是从bfcache中加载的,或者页面在卸载之后会被保存在bfcache中,那么persisted的值会被设置为true。因此,当第一次触发pageshow时,persisted的值一定是false,而在第一次触发pagehide时,persisted就会变成true(除非页面不会被保存在bfcache中)

window.addEventListener('pagehide', function(e) {
  console.log(e.persisted)
})
优秀文章首发于聚享小站,欢迎关注!
原文地址:https://www.cnblogs.com/yesyes/p/15352592.html