HTML5 history API 使用指南

MDN docs: Manipulating the browser history

DOMwindow对象通过history对象提供了对浏览器历史访问的功能。它暴露出实用的方法和属性以实现来回浏览用户的历史记录,除此之外,从HTML5开始提供了操作历史堆栈的相关功能。

#1 你可以在历史中随意穿梭

可以使用back(),forward(),go()这些方法,根据用户的历史记录进行浏览器的前进或者后退操作。

前进和后退

要通过历史记录进行后退操作,可以这样:

window.history.back()

这和你在浏览器工具栏中点击后退时的效果一样。

同样地,你可以进行前进操作(就像点击前进按钮一样):

window.history.forward()

移动到特定历史点

你可以使用go()方法从会话历史中加载特定的页面,以当前页面为定位基准(当前页面的index当然是0啦)。

后退一个页面(相当于调用back()方法):

window.history.go(-1)

前进一个页面(相当于调用forward()方法):

window.history.go(1)

同样地,你可以传入参数2来前进两个页面或者更多...

你可以通过查看length属性值来确定历史堆栈中的页数:

var numberOfEntries = window.history.length

Note: IE支持传递字符串URL作为参数给go(),这是非标准的,不被Gecko支持。


#2 添加和修改历史条目

HTML5 提出了history.pushState()history.replaceState()两个方法,分别用于添加和修改历史条目。这两个方法与window.onpopstate事件结合使用。

使用history.pushState()方法将会改变在更改状态后创建的XMLHttpRequest对象的HTTP头中使用的引用。这个引用将是创建XMLHttpRequest对象时window为this的文档的URL。

【附原文】:

Using history.pushState() changes the referrer that gets used in the HTTP header for XMLHttpRequest objects created after you change the state. The referrer will be the URL of the document whose window is this at the time of creation of the XMLHttpRequest object.

使用pushState()的例子

假设,在http://mozilla.org/foo.html页面执行下面的javascript:

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

这将导致地址栏显示http://mozilla.org/bar.html,然而并不会去加载bar.html或者检查bar.html是否存在。

假设现在用户现在导航到 http://google.com ,然后点击返回。此时,地址栏将会显示 http://mozilla.org/bar.html ,并且页面将获得一个popstate事件,其状态对象包含一个stateObj副本。页面本身将会看起来像foo.html,尽管页面可能会在popstate事件期间修改其内容。

如果我们再次点击返回,URL将会改变为 http://mozilla.org/foo.html,并且页面会获得另一个popstate事件,不同的是这次包含的是一个空的状态对象。文档的内容同样不会更改,尽管文档可能会在受到popstate事件后手动更新其内容。

pushState() 方法

pushState()方法具有三个参数:一个状态对象、标题(目前忽略)和URL(可选)。让我们详细说明这三个参数:

  • state object — 状态对象与由pushState()创建的新历史记录条目相关联。每当用户导航到新状态时,将触发一个popstate事件,且该事件的state属性包含历史条目的状态对象的副本。

    状态对象可以是任何可以被序列化的东西。因为FIrefox将状态对象保存到用户的磁盘,以便用户在重新启动浏览器后可以回复它们。我们在状态对象的序列化表示上强加了一个640k字符的大小限制。如果将序列化表示大于此值的状态对象传递给pushState(),则该方法会抛出异常。如果你需要比这更多的空间,建议使用seeeionStorage或者 localStorage

  • title — Firefox目前忽略此参数,将来可能会使用。在这里传递空字符串应该是安全的,以防未来更改方法。或者你可以传递一个title为你正移向的状态。

  • URL — 新的历史条目URL将由此参数给出。注意,调用pushState()之后,浏览器不会尝试加载此URL,但可能会在稍后尝试加载,例如在用户重新启动浏览器之后。新的URL不必是绝对地址;如果是相对地址,它将相对于当前URL进行解析。新的URL必须与当前URL同源;否则,pushState()将会抛出异常。此参数是可选的,如果没有特别指定,它将会默认为当前文档的URL。

Note: Gecko 2.0(Firefox 4 / Thunderbird 3.3 / SeaMonkey 2.1) 到 Gecko 5.0 (Firefox 5.0 / Thunderbird 5.0 / SeaMonkey 2.2)版本中,传递对象使用JSON进行序列化。从Gecko 6.0 (Firefox 6.0 / Thunderbird 6.0 / SeaMonkey 2.3)开始,传递对象使用the structured clone algorithm序列化。这将允许更多类型的对象被安全传递。

在某种意义上,调用pushState()相同于设置window.location = "#foo",两种方法都会创建和激活另一个与当前文档相关联的历史条目。但是pushState()有一些优点:

  • 新的URL可以是任何与当前页面同源的URL。相反,只有在你仅修改哈希值时,设置window.location才能保持在同一document
  • URL可以不变。相反,设置window.location = "#foo",如果当前哈希值不是#foo,则只创建一个新的历史记录条目。
  • 您可以将任意数据与新的历史记录条目相关联。使用基于hash的方法,您将需要将所有相关数据编码为短字符串。
  • 如果在以后浏览器开始使用title,则可以利用该数据(independent of, say, the hash)。

注意,pushState()不会导致hashchange事件被触发,即使新旧URL的不同之处仅仅在于哈希值。

在一个 XUL 文档中,它创建特定的XUL元素。

在其他文档中,它创建一个具有null命名空间URL的元素。

replaceState() 方法

history.replaceState()的操作几乎与history.pushState()相同,除了replaceState()会修改当前历史记录条目,而不是创建一个新的。注意,这并不妨碍在全局浏览器历史记录中创建新条目。

当你想要以更新state对象或改变当前历史记录条目的URL响应用户行为时,replaceState()非常有用。

Note:Gecko 2.0 (Firefox 4 / Thunderbird 3.3 / SeaMonkey 2.1)到Gecko 5.0 (Firefox 5.0 / Thunderbird 5.0 / SeaMonkey 2.2)版本,传递的对象使用JSON进行序列化。从Gecko 6.0 (Firefox 6.0 / Thunderbird 6.0 / SeaMonkey 2.3)开始,改为使用 the structured clone algorithm进行序列化。这将允许更多类型的对象被安全传递。

replaceState()的例子

假设在http://mozilla.org/foo.html页面执行下面的JavaScript:

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

与上例相同。

然后,假设在http://mozilla.org/bar.html执行下面的JavaScript:

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

这将导致URL栏显示为http://mozilla.org/bar2.html ,但并不会加载bar2.html或者检查其是否存在。

假设用户现在导航到 http://www.microsoft.com,然后点击返回。此时,URL栏将会显示 http://mozilla.org/bar2.html 。如果用户再次点击返回,URL栏将会显示 http://mozilla.org/foo.html ,完全会省略bar.html

popstate 事件

每次活动历史记录条目更改时,都会将一个popstate事件分派到window。如果活动中的历史记录条目是调用pushState创建或者是受replaceState的调用影响,popstate事件的state属性将包含历史记录条目的state对象的副本。

See window.onpopstate for sample usage.

读取当前状态

当你的页面加载时,它可能具有非空状态对象。这是可能会发生的,例如,如果页面设置了一个状态对象(使用pushState()replaceState()),然后用户重启了浏览器。当页面重新加载时,将会获得onload事件,而不是popstate事件。然而,如果你读取history.state属性,你将会得到一个状态对象,与触发popstate事件得到的状态对象相同。

你可以不必等待popstate事件读取当前历史记录条目的状态,使用history.state属性如下所示:

var currentState = history.state;

#3 实例

完整的AJAX web site例子,见:Ajax navigation example.


#4 规范

规范 状态 Comment
HTML Living StandardThe definition of 'History' in that specification. Living Standard No change from HTML5.
HTML5The definition of 'History' in that specification. Recommendation Initial definition.

# 5 浏览器兼容性

See also

posted @ 2017-09-16 19:40  t1ree  阅读(286)  评论(0编辑  收藏  举报