HTML5 history API

HTML5 history API

标签(空格分隔): JavaScripthtml


DOM window对象经过history对象提供了对浏览器历史的访问。它暴露了不少有用的方法和属性,容许你在用户浏览历史中向前和向后跳转,同时,从HTML5开始提供了对history栈中内容的操做。html5

1、 在history中跳转

使用back()forward()go()方法来完成在用户历史记录中向后和向前跳转。git

// 在history中向后跳转
window.history.back();
window.history.go(-1);

// 向前跳转
window.history.forward();
window.history.go(1);

// 当前页
window.history.go(0);

2、添加和修改历史记录中的条目 (pushState()replaceState())

HTML5引入了history.pushState()history.replaceState()方法,他们分别能够添加和修改历史记录条目。这些方法一般与window.onpopstate配合使用。github

使用history.pushState()能够改变referrer(引用),它在用户发送XMLHttpRequest请求时在HTTP头部使用,改变state后建立的XMLHttpRequset对象的referrer都会被改变。由于referrer是标识建立XMLHttpRequest对象时this所表明的window对象中document的URL。ajax

pushState()方法示例api

假设有如下几个文件浏览器

假设在http://demo.com/foo.html中执行了一下js代码:安全

var stateObj = { foo: 'bar' };
window.history.pushState(stateObj, 'page 2', 'bar.html');

这将使浏览器地址栏显示为http://demo.com/bar.html,但并不会致使浏览器加载bar.html,甚至不会检查bar.html是否存在。以下图所示:session

图1

如今假设用户又访问了下面的连接http://demo.com/other.html,而后点击了返回按钮。此时,地址栏将显示http://demo.com/bar.html,同时页面会触发popstate事件,事件对象state中包含了stateObj的一份拷贝。页面自己与foo.html同样,尽管其在popstate事件中可能会修改自身内容。wordpress

若是咱们再次点击返回按钮,页面URL会变为http://demo.com/foo.html,文档对象document会触发另一个popstate事件,这一次的事件对象state object为null。这里也同样,返回并不改变文档的内容,尽管文档在接受popstate事件时可能会改变本身的内容,其内容仍与以前的展示一致。

pushState()方法

pushState()须要三个参数:一个状态对象,一个标题(目前被忽略)和一个URL(可选的)。

  • 状态对象

    状态对象state是一个js对象,经过pushState()建立新的历史记录条目。不管何时用户导航到新的状态,popstate事件就会被触发,且该事件的state属性包含该历史记录条目状态对象的副本。

    状态对象能够是能被序列化的任何东西。缘由在于火狐将状态对象保存在用户的磁盘上,以便用户重启浏览器时使用,咱们规定了状态对象在序列化表示后有640k的大小限制。若是你给pushState()方法传了一个序列化后大于640k状态对象,该方法会抛出异常。若是你须要更大的空间,建议使用sessionStorage以及localStorage。

  • 标题

    火狐目前忽略这个参数,但将来可能会用到。传递一个空字符串在这里是安全的,而在未来这是不安全的。二选一的话,你能够为跳转的state传递一个短标题。

  • URL

    该参数定义了新的历史URL记录。注意,调用pushState()后浏览器并不会当即加载这个URL,但可能会在稍后某些状况下加载这个URL,好比在用户从新打开浏览器时。新URL没必要须为绝对路径。若是新URL是相对路径那么它将被做为相对于当前URL处理。新URL必须与当前URL同源,不然pushState()会抛出一个异常。该参数是可选的,缺省为当前URL。

某种意义上,调用pushState()与设置widnow.location = '#ff'相似,两者都会在当前页面建立并激活新的历史记录。但pushState()有如下几条优势:

  • 新的URL能够是与当前URL同源的任意URL。而设置window.location仅当你只修改了哈希值时才保持同一个document。
  • 若是须要,你能够没必要改变URL。而设置window.location = '#foo';在当前哈希不是#foo的状况下,仅仅是新建了一个新的历史记录选项。
  • 你能够为新的历史记录项关联任意数据。而基于哈希值的方式,则必须将全部相关数据编码到一个短字符串里。
  • 假如标题在以后会被浏览器用到,那么这个数据是能够被使用的(哈希则不能)。

注意pushState()绝对不会触发hashchange事件,便是是新的URL与旧的URL仅哈希不一样也不会触发。

在XUL文档中,它建立指定的XUL元素。

在其它文档中,它建立一个命名空间为URI为null的元素。

replaceState()方法

history.replaceState()的使用与history.pushState()很是类似,区别在于replaceState()是修改了当前的历史记录项而不是新建一个。注意这并不会阻止其在全局浏览器历史记录中建立一个新的历史记录项。

replaceState()的使用场景在于为了响应用户操做,你想要更新状态对象state或者当前历史记录的URL。

replaceState()示例

假设http://demo.com/foo.html执行了以下js代码:

var stateObj = { foo: 'bar' };
window.history.pushState(stateObj, 'page 2', 'bar.html');

假设接着执行了以下代码:

window.history.replaceState(stateObj, 'page 3', 'bar2.html');

这将会致使地址栏显示http://demo.com/bar2.html,可是浏览器并不会去加载bar2.html甚至不须要检查bar2.html是否存在。

图2

假设如今用户从新导向了http://demo.com/other.html,而后点击了回退按钮,这里地址栏会显示http://demo.com/bar2.html,再次点击回退,地址栏显示foo.html彻底跳过了bar.html

popstate事件

每当活动的历史记录项发生变化时,popstate事件都会被传递给window对象。若是当前活动的历史记录项是被pushState建立的,或者是由replaceState改变的,那么popstate事件的状态属性state会包含一个当前历史记录状态对象的拷贝。

获取当前状态

页面加载时,或许会有个非null的状态对象。这是有可能发生的,你能够读取当前历史记录项的状态对象state,而没必要等待popstate事件,只须要这样使用history.state属性:

var currentState = history.state;

3、window.onpopstate

window.onpopstatepopstate事件在window对象上的事件处理程序。

每当处于激活状态的历史记录条目发生变化时popstate事件就会在对应window对象上触发。若是当前处于激活状态的历史记录条目事由history.pushState()方法建立,或者由history.replaceState()方法修改过的,则popstate事件对象的state属性包含了这个历史记录条目的state对象的一个拷贝

调用history.pushState()或者history.replaceState()不会触发popstate事件。popstate事件只会在浏览器某些行为下触发,好比后退前进或者在js中调用back()等的方法。

当网页加载时,各浏览器对popstate事件是否触发有不一样的表现,Chrome和Safari会触发popstate事件,而FireFox不会。

onpopstate语法

window.onpopstate = funcRef;
// funcRef是个函数名

popdtate事件

假如当前网页地址为http://demo.com/example.html,则运行下述代码后:

window.onpopstate = function(event) {
  alert("location: " + document.location + ", state: " + JSON.stringify(event.state));
};
//绑定事件处理函数. 
history.pushState({page: 1}, "title 1", "?page=1");    //添加并激活一个历史记录条目 http://demo.com/example.html?page=1,条目索引为1
history.pushState({page: 2}, "title 2", "?page=2");    //添加并激活一个历史记录条目 http://demo.com/example.html?page=2,条目索引为2
history.replaceState({page: 3}, "title 3", "?page=3"); //修改当前激活的历史记录条目 http://de..?page=2 变为 http://de..?page=3,条目索引为3
history.back(); // 弹出 "location: http://demo.com/example.html?page=1, state: {"page":1}"
history.back(); // 弹出 "location: http://demo.com/example.html, state: null
history.go(2);  // 弹出 "location: http://demo.com/example.html?page=3, state: {"page":3}

即使进入了那些非pushState和replaceState方法做用过的(好比http://demo.com/example.html)没有state对象关联的那些网页, popstate事件也仍然会被触发。

初始打开页面:
图3

back一次:
图4

back二次:
图5

源码示例

4、兼容性

Desktop

特性 Chrome Edge FireFox IE Opera Safari
replaceState, pushState 5 Yes 4.0 10 11.50 5.0
history.state 18 Yes 4.0 10 11.50 6.0

5、实例

参见《ajax与HTML5 history pushState/replaceState实例》

Ajax能够实现页面的无刷新操做——优势;可是,也会形成另外的问题,没法前进与后退。

当执行Ajax操做的时候,往浏览器history中塞入一个地址(使用pushState)(这是无刷新的);因而,返回的时候,经过URL或其余传参,咱们就能够还原到Ajax以前的模样。

效果如图所示(源码地址):

图6

相关文章
相关标签/搜索