【发布时间】:2013-06-07 22:15:17
【问题描述】:
在我的单页网络应用程序中,我希望在某些页面上有一个后退按钮,可以将用户带回到浏览器历史记录中的特定点:不一定是上一页。
请注意,我不是在谈论浏览器的后退按钮,它应该像往常一样工作。
用例
例如,考虑 gmail 网络应用程序。有一个文件夹视图,可能带有搜索过滤器或其他参数,然后是一个显示单个消息的消息视图。在消息视图中,有一个后退按钮不会将您带到上一页:即使您单击了几条消息,后退按钮也会将您带回到原来的文件夹视图,然后再单击任何的消息。
在 gmail 的情况下,这可以通过简单地在 URL 末尾编码之前的状态来实现。例如,如果您通过搜索找到此消息,它将是:
#search/stuff/<MESSAGE_ID>
由此,应用知道后退按钮应该指向页面:
#search/stuff
然而,在我的应用程序中,有太多的状态无法将其全部编码到 URL 中。不是两个视图(文件夹 + 消息),而是三个视图,我们称它们为 A、B 和详细信息,其中 A 和 B 都有大量可能的过滤器和编码在 URL 中的选项,我想在何时保留这些过滤器和选项例如从 B 到 A 或从细节返回到 B。在细节页面的 URL 中对 A、B 和细节的所有参数进行编码会使 URL 非常笨拙。
实施
我认为这可以使用 html5 历史 API 轻松实现。但是,据我所知,历史 API 不支持读取历史中的 URL:您只能盲目地向后或向前。
history.js 提供对过去状态的访问,如相关问题中所述:
History API: Javascript Pushstate, get previous URL
但是,我使用的 angularjs 不适用于 history.js,因为它直接与 history api 对话,而不是通过 history.js,所以由 angular $location 服务引起的转换状态不会显示在 history.js 的 History 对象中。
看来我需要做以下事情之一:
- 让 history.js 与 angular 完美配合
- 在我自己的代码中重新实现 history.js 的一部分功能
我还考虑使用 document.referrer 来查看历史记录中的前一个值,但这不起作用,因为在单页应用程序中导航时它没有设置。
【问题讨论】:
-
你可以添加你自己的 onpopstate 或 onhashchange 来记录每一个 url 的变化,不管是谁做的。然后你有一个过去的 URL 列表,就像历史一样。此外,使用原生 pushState,您可以将大状态与 url 关联而不对其进行编码,它与 url 的参数不同。
-
@dandavis:我已经做到了,但是我在哪里存储这些信息?如果我不存储它,整个页面重新加载将丢失历史记录。如果我将它存储在 sessionStorage 中,并且用户在两个选项卡中打开我的页面,我如何避免两个选项卡的历史相互干扰?
-
好的,看来我可以简单地使用 sessionStorage,因为快速测试确认 sessionStorage 不是跨选项卡共享的。
-
您不必对 URL 中的所有数据进行编码。只需使用与对象文字中的键匹配的 ID,该对象文字包含特定状态所需的所有内容。
-
@dandavis:另外,onpopstate/onhashchange 并没有告诉我历史上是要倒退还是前进……
标签: javascript angularjs history.js html5-history