当前位置: 美高梅棋牌 > 软件资讯 > 正文

History API 与浏览器历史堆栈管理

时间:2019-12-04 02:40来源:软件资讯
History API 与浏览器历史堆栈管理 2016/07/25 · HTML5 ·History,HTML5,浏览器 本文作者: 伯乐在线 -欲休。未经作者许可,禁止转载! 欢迎加入伯乐在线 专栏作者。 移动端开发在某些场景中有

History API 与浏览器历史堆栈管理

2016/07/25 · HTML5 · History, HTML5, 浏览器

本文作者: 伯乐在线 - 欲休 。未经作者许可,禁止转载!
欢迎加入伯乐在线 专栏作者。

移动端开发在某些场景中有着特殊需求,如为了提高用户体验和加快响应速度,常常在部分工程采用SPA架构。传统的单页应用基于url的hash值进行路由,这种实现不存在兼容性问题,但是缺点也有–针对不支持onhashchange属性的IE6-7需要设置定时器不断检查hash值改变,性能上并不是很友好。

而如今,在移动端开发中HTML5规范给我们提供了一个History接口,使用该接口可以自由操纵历史记录。本文并不详细介绍History接口,而是探究History接口如何影响浏览器历史堆栈,并且利用这个规律应用到具体的实际业务中,提出两种历史记录保存策略,使路由逻辑更清晰,让SPA更容易。

原文:抱歉找不到了

History API回顾

HTML5 History API包括2个方法:history.pushState()和history.replaceState(),和1个事件:window.onpopstate。

HTML5 的 History API 可以让开发者不刷新整个页面就可以修改网站的 URL。这在使用 JavaScript 加载一个页面的一部分的时候尤其有用,用 JavaScript 新加载的这一部分内容是明显不同的, 因而有必要使用一个新的 URL(原文: This is particularly useful for loading portions of a page with JavaScript, such that the content is significantly different and warrants a new URL.)。

pushState

history.pushState(stateObject, title, url),包括三个参数。

第一个参数用于存储该url对应的状态对象,该对象可在onpopstate事件中获取,也可在history对象中获取。

第二个参数是标题,目前浏览器并未实现。

第三个参数则是设定的url。一般设置为相对路径,如果设置为绝对路径时需要保证同源。

pushState函数向浏览器的历史堆栈压入一个url为设定值的记录,并改变历史堆栈的当前指针至栈顶。

> 在这里笔者使用历史堆栈和当前指针,用以说明浏览器对历史记录的管理策略。文档中并没有使用这样的词汇,笔者为了更形象的介绍接口对浏览器历史记录的影响,使用这样的描述,如有不当之处请及时指出(不过目前以这套模型为基础的逻辑实现中并未出现悖论)。

这里有一个例子,我们假设一个人从一个网站的 Homepage 前往访问 Help 页面。我们使用 Ajax 加载 Help 页面的内容。那个用户随后又访问 Product 页面,而我们还是用 Ajax 加载并替换内容。然后,用户想分享这个页面(即 Product 页面)的 URL。通过 History API,我们本可以(we could have been)随着用户的访问而正确地修改页面的 URL,所以他们看见(或分享或保存)的 URL 是相关的并且正确的。

replaceState

该接口与pushState参数相同,含义也相同。唯一的区别在于replaceState是替换浏览器历史堆栈的当前历史记录为设定的url。需要注意的是,replaceState不会改动浏览器历史堆栈的当前指针。

基础原理

要查看这个 API 的特征,只需要打开 the Developer Tools(即浏览器的开发者工具),在控制台输入(type into)history。如果你选择的浏览器支持这个 API,那么我们将会看到许多隶属于这个对象的方法(a host of methods attached to this object):

History {length: 2, state: null, scrollRestoration: "auto"}
    length:2
    scrollRestoration:"auto"
    state:null
    __proto__:History
        back:back()
        constructor:History()
        forward:forward()
        go:go()
        length:(...)
        get length:()
        pushState:pushState()
        replaceState:replaceState()
        scrollRestoration:(...)
        get scrollRestoration:()
        set scrollRestoration:()
        state:(...)
        get state:()
        Symbol(Symbol.toStringTag):"History"
        __proto__:Object

我们只对说明中的pushStatereplaceState感兴趣。回到控制台,我们可以试验一下这些方法并看看当我们使用这些方法的时候 URL 发生什么变化。我们稍后将覆盖其他参数,但现在我们所要使用的是最后的这个参数:

history.replaceState(null, null, 'hello');

尽管没有请求资源,窗口也保持着同一个页面,但上面的replaceState方法用/hello作为地址栏中 URL 的结尾(原文:The replaceState method above switches out the URL in the address bar with '/hello' despite no assets being requested and the window remaining on the same page. )。这里还有一个问题。当点击浏览器上的返回按钮的时候,我们会发现我们并没有返回到这篇文章的 URL ,而是回到我们之前所停留的页面。这是因为replaceState没有处理浏览器的历史,它只是简单地替换地址栏中当前的 URL。

要解决(fix)这个问题,我们需要使用pushState方法来代替:

history.pushState(null, null, 'hello');

现在,如果我们点击浏览器的返回按钮,我们会发现它会像我们所希望的一样运行,因为pushState已经修改了我们的历史(记录)以包含我们刚刚所传递进去的 URL。这很有趣,但如果我们做一些不那么直接的尝试并且假装当前的 URL 一直都不是“css-tricks.com”而是完完全全是另一个网站,之后会发生什么呢?

history.pushState(null, null, 'https://twitter.com/hello');

这会抛出一个异常,因为 URL 必须与当前的 URL 同源(has to be of the same origin as the current one),否则,我们可能冒着重大的安全漏洞风险(原文:we might risk major security flaws )并且是开发者能够欺骗人们让他们完全相信自己是在一个不同的网站(give developers the ability to fool people into believing they were on a different website altogether)。

回头看看被传入到这个函数中的其他参数,我们可以总结如下:

history.pushState([data], [title], [url]);
  1. 如果网页的状态改变了,例如:每当有人按下浏览器中的返回或前进按钮,我们将需要的数据就是第一个参数。需要注意的是:在 Firefox 中,这个数据被限制为 640k 个字符。
  2. title是第二个参数,他可以是一个字符串,但截至本文写作时间(2015年3月9日),所有浏览器都简单地忽略它。
  3. 最后的这个参数就是我们希望出现在地址栏的 URL。

onpopstate

该事件是window的属性。该事件会在调用浏览器的前进、后退以及执行history.forward、history.back、和history.go触发,因为这些操作有一个共性,即修改了历史堆栈的当前指针。在不改变document的前提下,一旦当前指针改变则会触发onpopstate事件。

简史(A Quick History)

这些 history API 最值得注意的是,它们不会重新加载页面。在过去,改变 URL 的唯一方法是window.locaton,但它总是会重新加载页面。 除非,如果你所改变的只是hash(就像 点击<a href="#target">link</a>不会重新加载页面 一样)(原文:Except, if all you changed was the hash)。

这与旧的 hashbang 方法相通,hashbang 方法可以改变 URL 而不刷新整个页面。总所周知,Twitter 曾经这样子做并因此而在很大程度上收到了批评(hash 不是一个真的资源地址)。

Twitter 放弃了使用这个方法,并且成为 history API 最早的支持者之一。

图片 1

Paste_Image.png

编辑:软件资讯 本文来源:History API 与浏览器历史堆栈管理

关键词: