javascript - 根据历史自定义后退按钮

标签 javascript angularjs history.js html5-history

在我的单页网络应用程序中,我希望在某些页面上有一个后退按钮,使用户返回到浏览器历史记录中的特定点:不一定是上一页。

请注意,我不是在谈论浏览器的后退按钮,它应该照常工作。

用例

例如,请考虑 gmail 网络应用程序。有一个文件夹 View ,可能带有搜索过滤器或其他参数,然后是一个显示单个消息的消息 View 。在消息 View 中,有一个不会将您带到上一页的后退按钮:即使您单击阅读了几条消息,后退按钮也会将您带回到您最初来自的文件夹 View ,然后再单击任何的消息。

对于 gmail,这是通过简单地在 URL 末尾编码先前的状态来实现的。例如,如果您通过搜索找到此消息,它将是:

#search/stuff/<MESSAGE_ID>

由此,应用程序知道后退按钮应指向具有以下内容的页面:

#search/stuff

然而,在我的应用程序中,有太多状态无法在 URL 中对其进行编码。不是两个 View (文件夹 + 消息),而是三个 View ,我们称它们为 A、B 和详细信息,A 和 B 都有大量可能的过滤器和选项编码在 URL 中,我想在例如从B返回A或从详情返回B。将A、B和详情的所有参数编码在详情页面的URL中会使URL非常笨重。

实现

我认为这可以使用 html5 history API 轻松实现。然而,据我所知,历史 API 不支持读取历史中的 URL:你只能盲目地后退或前进。

history.js 提供对过去状态的访问,如相关问题中所述:

History API: Javascript Pushstate, get previous URL

但是,我使用的 angularjs 不能很好地与 history.js 一起使用,因为它直接与历史 api 对话而不是通过 history.js,所以由 angular $location 服务引起的转换状态不显示在 history.js 的历史对象中。

看来我需要执行以下操作之一:

  • 让 history.js 与 angular 一起工作
  • 在我自己的代码中重新实现 history.js 的一部分功能

我还考虑过使用 document.referrer 来查看历史记录中的先前值,但这不起作用,因为在单页应用中导航时不会设置它。

最佳答案

在回答我自己的问题时,我选择了@MaxArt 在他的评论中建议的更简单的解决方案。

  • 为页面生成一个随机 ID
    • 因为我使用 angularjs,所以我这样做 $on('$routeChangeSuccess') 或 $on('$routeUpdate')
    • 如果没有 angularjs,我想我会在 popstate 上这样做
  • 在 sessionStorage 中存储从这个随机 ID 到我需要的所有 URL 信息(在我的例子中是搜索和路径)的映射
  • 在我的应用程序的概念层次结构中前进的传出链接中包含来自=当前页面的 ID 的搜索参数
  • 单击自定义后退按钮时,使用 from seach 参数在 sessionStorage 中查找我来自的状态
    • 如果找到,返回到该 URL
    • 如果找不到(用户直接导航到此页面),返回到应用层次结构中上一个 View 的默认 URL

采用这种方法而不是构建过去 URL 历史记录的更一般方法的理由:

  • 如前所述,pushState API 不提供对过去 URL 的访问
  • 将提供该信息的 History.js 集成到 angularjs 中似乎并不简单
    • angularjs 在内部使用 history API:它需要更改为使用 History
  • 实现自定义代码以在 sessionStorage 中记录 URL 历史记录也并非易事。主要问题是,缺乏与浏览器历史记录的集成,似乎没有一种通用的方法来知道访问的页面是新的还是通过浏览器历史记录中的一个或多个步骤返回访问的。如果有人可以提出解决方案,我很乐意对此进行纠正 (1)
  • 使用 History.js 或任何用附加代码包装所有 history.pushState 的等效解决方案,要求页面上的几乎所有链接都包装在 History.pushState 中,否则 URL 更改不会显示在历史记录中。<

(1) How do I retrieve if the popstate event comes from back or forward actions with the HTML5 pushstate?

关于javascript - 根据历史自定义后退按钮,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17054688/

相关文章:

javascript - animationend 在递归函数中不起作用

javascript - 如何使用 Javascript XMLHttpRequest 将 JSON 数据对象发送到服务器?

javascript - 抗锯齿 :true in Threejs 的 FPS 性能不佳

reactjs - 如何使用浏览器后退/前进按钮导航 React 状态更改历史记录

javascript - 正则表达式 - 验证密码条件 - 三分之二

javascript - 单页 Angular 应用的自动化前端性能测试

javascript - 添加服务和过滤器或多个服务时,我在做什么导致未知提供者

AngularJS ng-table 无法将属性 '$data' 设置为 null

javascript - 浏览器后退和前进按钮不使用 history.js 的 statechange 事件调用回调方法

javascript - 每当我执行推送状态时,Statechange 就会触发