HTML5历史记录API

时间:2020-01-09 10:34:38  来源:igfitidea点击:

HTML5历史记录API使我们可以通过JavaScript访问浏览器导航历史记录。 HTML5历史记录API在单页Web应用程序中非常有用。单页Web应用程序可以使用HTML5历史记录API来使应用程序中的某个状态"可书签"。稍后,我将回到如何使用历史记录API在单页应用程序中建立可书签状态。

历史堆栈

浏览历史由一堆URL组成。每次用户在同一个网站中浏览时,新页面的URL都会放在堆栈的顶部。当用户单击"后退"按钮时,堆栈中的指针将移动到堆栈中的上一个元素。如果用户再次单击"前进"按钮,则指针将向前移到堆栈上的最顶层元素。如果用户单击"后退",然后单击新链接,则堆栈中最顶层的元素将被新的URL覆盖。

这是历史记录堆栈的示例:

http://myapp.com/great-new-story.html
http://myapp.com/news.html
http://myapp.com

在上述历史记录堆栈中最后访问的页面是http:// myapp.com / great-new-story.html。如果用户单击"后退"按钮,则历史记录堆栈中的指针将移回到http:// myapp.com / news.html。如果用户单击"前进"按钮,则历史记录堆栈指针将向前移至" http://myapp.com/great-new-story.html",但是如果用户单击另一个链接(位于" http :// myapp.com / news.html页),则该链接的URL将覆盖历史记录堆栈上的http:// myapp.com / news.html

HTML5历史记录API使Web应用程序可以访问该历史记录堆栈。

HTML5历史记录API安全限制

HTML5历史记录API仅允许网页访问部分浏览历史记录,该部分与网页本身位于同一域中。出于安全原因,历史记录API中的此限制是必需的,因此网页无法查看用户访问过哪些其他网站。

类似地,HTML5历史记录API不允许网页将URL推入历史记录堆栈中,该URL与网页的域不在同一域中。该限制确保了网页不能假装已将用户转发给例如当用户开始输入时,Paypal并嗅探其用户名/密码等。

历史对象

我们可以通过" history"对象访问浏览历史记录,该对象在JavaScript中可以作为全局对象使用(实际上是" window.history")。

" history"对象包含组成历史API的以下函数:

  • back()
  • forward()
  • go(index)
  • pushState(stateObject,title,url)
  • replaceState(stateObject,title,url)

back()函数将浏览历史记录移回到上一个URL。调用back()具有与用户单击浏览器的"后退"按钮相同的效果。

forward()函数将浏览历史记录向前移动到历史记录的下一页。调用" forward()"与单击浏览器的" forward"按钮具有相同的效果。仅当调用了back()函数或者单击了"后退"按钮时,才有可能。如果历史记录已指向浏览历史记录中的最新URL,则没有任何前进的方向。

go(index)函数可以根据我们作为参数传递给go()函数的索引来向前或者向后移动历史记录。如果我们使用负数索引(例如" go(-1)")调用" go()",则浏览器将返回历史记录。如果我们将肯定索引传递给go()函数,则浏览器会在浏览历史记录中前进(例如go(1))。索引指示历史记录中要在浏览历史记录中前进或者后退的步数,例如1,2,-1,-2等

pushState(stateObject,title,url)函数将一个新的URL推送到历史堆栈中。该函数具有三个参数。 " URL"是要推送到历史记录堆栈的URL。浏览器通常会忽略" title"参数。 stateObject是一个对象,当将新的URL推送到历史记录堆栈时,该对象将与触发的事件一起传递。这个stateObject可以包含你想要的任何数据。它只是一个JavaScript对象。

replaceState(stateObject,title,url)函数的作用类似于pushState()函数,不同之处在于它用新的URL替换了历史记录堆栈中的当前元素。当前元素不一定是最重要的元素。如果已经在history对象上调用了back()forward()go()函数,则它是当前指向的元素,可以是堆栈中的任何元素。

历史API示例

现在该来看一些有关如何使用HTML5历史记录API的示例。

back()和forward()

让我们首先来看一下如何使用back()forward()函数在历史记录中来回移动:

history.back();

history.forward();

请记住,history对象位于window对象中,因此我们还可以编写:

window.history.back();

window.history.forward();

但是,由于" window"对象是默认对象,因此我们可以将其省略。在本教程的其余部分中,我将忽略" window"对象。

请记住,除非我们(或者用户)先移回历史记录,否则我们将无法移入历史记录。

go()

现在让我们看看如何使用go()函数执行类似于back()和forward()函数的动作。首先,这是我们使用go()在浏览历史记录中后退一步的方式:

history.go(-1);

要后退两步,我们需要将-2作为参数传递给go()函数,如下所示:

history.go(-2);

同样,要使历史向前发展,我们可以将正索引传递给go()函数。这是两个在历史上向前推进了一步和两个步骤的示例:

history.go(1);

history.go(2);

当然,如果我们同时执行了这两行,则浏览历史记录将总共向前移动3个步骤。

pushState()

要将状态推入历史堆栈,请调用" history"对象的" pushState()"函数。这是一个pushState()示例:

var state = {};
var title = "";
var url   = "next-page.html";

history.pushState(state, title, url);

本示例将新的URL推送到历史记录堆栈中。这还将更改浏览器的地址字段中的URL,但不会导致浏览器尝试加载该URL。

replaceState()

replaceState()函数替换了当前指向的历史记录堆栈中的history元素。如果用户已使用"后退"按钮将其移回历史记录,则这可能不是最重要的元素。这是一个replaceState()示例:

var state = {};
var title = "";
var url   = "another-page.html";

history.replaceState(state, title, url);

替换状态还将更改浏览器的地址字段中的URL,但不会使浏览器加载该URL。替换URL的页面仍保留在浏览器中。

历史变更事件

HTML5历史记录API使网页能够侦听浏览器历史记录中的更改。安全限制也适用于此,因此不会向网页通知导致URL超出网页域之外的历史记录更改。

要侦听浏览器历史记录中的更改,请在"窗口"对象上设置一个" onpopstate"侦听器。这是浏览器历史记录事件侦听器示例:

window.onpopstate = function(event) {
    console.log("history changed to: " + document.location.href);
}

每次浏览器历史记录在同一页面(页面推送到历史记录堆栈中的浏览器历史记录)内更改时,都会调用" onpopstate"事件处理函数。对历史记录更改事件的反应可能是从URL中提取参数并将相应的内容加载到页面中(例如,通过AJAX)。

注意:仅由"后退"或者"前进"按钮或者相应的历史记录导航功能" back()"," forward()go()"引起的更改将导致" onpopstate"事件侦听器获取叫。调用pushState()replaceState()函数不会触发历史更改事件。

在实践中使用History API

当将新的URL推入历史记录堆栈时,浏览器的地址字段中的URL将更改为新的URL。但是,浏览器不会尝试加载该URL。仅显示URL并将其推入堆栈,就像浏览器已访问该页面一样,但是推送新状态的页面仍保留在浏览器中。

将新URL推送到历史记录堆栈是一种使单页应用程序(SPA)中的特定状态可添加书签的有用方法。例如,在单页在线商店中,应用程序的URL可能是:

http://myshop.com

该应用程序可能能够在同一页面上向用户显示产品,但是用户如何将指向特定产品的链接发送给朋友?

解决方案是,在加载新产品时,单页面应用会将新URL推送到历史记录堆栈中。这不会导致新URL的加载,但确实会使新URL在浏览器的地址字段中可见。从这里可以将其添加书签或者复制粘贴到电子邮件等中。以下是这样一个可添加书签的URL外观的示例:

http://myshop.com?productId=234

或者,也许是一个更具可读性的URL:

http://myshop.com/products/234

或者是一个略多于REST的版本(也提到了产品的类型):

http://myshop.com/products/books/234

在将此URL推送到浏览历史记录之后,Web商店页面将通过AJAX加载相应的产品并将其显示给用户。

如果用户单击"后退"按钮,则将调用" onpopstate"事件处理程序。然后,网页应查看新的URL是什么,如果URL返回到http://myshop.com,则加载与该URL对应的产品或者应用程序的首页。

这是一个HTML5代码示例,说明了使用AJAX将数据加载到浏览器中的原理:

<a href="javascript:push('http://myshop.com/books/123');">
    Book 123
</a> <br/>
<a href="javascript:push('http://myshop.com/apps/456');">
    App 456
</a>

<script>
function loadUrl(url) {
    console.log("loading data from url: " + url);
}

function push(url) {
    history.pushState(null, null, url);
    loadUrl(url);
}

window.onpopstate = function(event) {
    console.log("history changed to: " + document.location.href);
    loadUrl(document.location.href);
}
</script>

本示例包含两个具有JavaScript Click侦听器的链接。单击链接之一后,相应的URL将被推入历史记录堆栈,然后加载到浏览器中。

该示例还包含一个" onpopstate"事件监听器。当用户单击"后退"或者"前进"按钮时,此事件侦听器将加载浏览器地址字段现在显示的任何URL。

配置服务器

如果用户单击链接和"后退" /"前进"按钮,则前面显示的示例将起作用。但是,如果用户将URL发送给朋友或者将其添加为书签并稍后访问,该怎么办?

如果用户尝试访问带有书签的URL" http://myshop.com/books/123",则浏览器将向Web服务器请求该URL。 Web服务器需要知道它必须发送回与从URLhttp:// myshop.com发送回的相同的单页应用程序。我们将需要配置Web服务器来执行此操作。

同样,单页Web应用程序必须查看首次加载时使用的URL,并使用该URL确定要加载和显示的内容。因此,如果单页应用程序加载了URLmyshop.com / books / 123,则该应用程序应加载相应的产品并进行显示。此URL检查必须在单页应用程序初始化期间进行。

浏览器对HTML5历史记录API的支持

在撰写本文时,除Opera Mini外,所有现代浏览器(IE,Safari,Chrome,Firefox)都支持HTML5历史记录API。