浏览器历史管理

时间:2012-11-27 03:14:34

标签: javascript html gwt back-button browser-history

我试图找到一种干净的解决方案,以最有效的方式使用浏览器历史记录。 (我使用GWT,但这个问题确实比这更普遍。)

这是我的情况(我认为这很标准):

我有一个Web应用程序,它有几个不同的页面/位置/位置(无论你想叫它),我会根据浏览器历史记录的变化显示它。除了通常的" Home"," Features"," Contact"等等,这些都是静态HTML页面,还有一个" User"部分,人们可以登录他们的用户帐户并(让我们称之为)"项目"用户可以在其中处理项目的部分。

所以,现在我只使用名为 #Home #Features #Contact 等的本地链接,以及 #User #Project 以访问不同的页面。一切都很好,除了以下情况:

例如,如果有人打开链接 #Project ,则会向该人显示项目登录对话框。这个登录对话框有一个 cancel 按钮,我想通过从我的应用程序调用浏览器的 back 按钮来实现它(很简单)。我想这样做的原因有两方面:

  1. 您可以从应用中的多个不同位置以及书签进入此登录对话框,使用此方法,我无需跟踪用户来自何处。
  2. 更重要的是:如果我确实记得用户来自哪里(例如 #Home )并且链接了用户"转发"返回那个地方,我得到以下效果:
    • 假设用户访问 #Home ,然后 #Features ,然后点击项目登录。
    • 如果用户点击取消按钮,我发送给他"转发"到 #Features ,然后点击浏览器的后退按钮会返回登录对话框,然后再次 #Features ,最后 #Home 。不是你想要的。
    • 相反,如果我只是通过浏览器的后退功能实现 cancel ,那么您想立即回到 #Home
  3. 此时一切都很棒,除非用户最初通过指向 #Project 的直接书签链接进入此登录对话框。因为那时,如果我只是取消 = 返回,用户就会被完全从页面发送回浏览器的起始页面或者之前的任何地方。所以,在这种情况下,我确实需要链接"转发"到 #Home

    现在,我已经尝试了几种方法来解决这个问题,并提出了几个解决方案,但似乎没有一个对我来说非常可取,但是让我分享它们可能会激起一些创造力:

    • 首次打开页面时,请抓住历史记录标记。如果它是 #Project #User 或触发可取消对话框的任何其他内容,请将以下项目放入历史记录堆栈: #Home #Project ,其中最后一个是保存的初始令牌。然后,这允许我的 cancel 按钮正常运行...一次......但是,如果用户之后点击返回,他将再次获得登录对话框(因为原始历史记录仍在历史堆栈中,我不知道如何清除它。点击 cancel 然后将他带离页面(行为不一致)。
    • 我可以将#+++ #Home #Project 放到堆栈上,这样我就可以抓住了 back 点击这会将用户从网页上移开,方法是检测#+++ 链接,然后只需将 #Home 令牌重新添加到堆。这样可以解决问题并且整体上工作得很漂亮,除了我讨厌那些不会让你退出它们的网站而不用足够快地敲击后退按钮......
    • 最干净的解决方案是,如果我可以以某种方式跟踪历史堆栈的长度,就我的应用程序中的位置而言。一开始就很容易:它上面有一个项目。但是如果我得到一系列这样的地方怎么办: #Home #Features #Home ?用户是否单击返回返回 #Home ,即浏览器中的历史记录现在为1,或者是否点击 #Home link,即历史长度为3?我想检测这个的想法是:
      • 定义, #Home #home 相同。
      • 让页面中的所有链接仅链接到链接的大写版本。
      • 每当您收到以。开头的历史记录更改通知时 大写字母,立即在历史记录中再添加两个项目, 第一个以小写字母开头,第二个以大写字母开头。即 #Home 变为 #Home #home #Home
      • 如果您的历史记录更改以小写字母开头,您知道用户只是点击返回而不是链接,只需点击返回两个他有更多时间回到上一页。
      • 现在你可以区分"向后"和"前进"在代码中链接并维护准确的历史模型。
      • 但是,遗憾的是,这有两个问题:首先,浏览器历史记录混乱(不是非常优雅),其次,系统开始崩溃,如果用户曾经足够快地点击返回,以便您的应用没有时间对消息作出反应。

    这似乎应该是一个非常普遍的问题,我希望你们中的一个能指出一个比我的想法更有用的方向。

3 个答案:

答案 0 :(得分:1)

window.history具有length属性,该属性将显示当前标签的历史记录中有多少条目。遗憾的是可过滤(因此无法说出window.history.localURLs.length)。

如果您几乎完全在客户端执行此操作(即部分更新,极少数整页加载,使用哈希或history.(push|pop)State API),那么您可能需要考虑合并客户端路由框架进入你的应用程序,以避免重新发明轮子。

答案 1 :(得分:1)

在用户访问#LOGIN对话框之前,将执行您的入口点类。在本课程中,您可以记住最后一个已知页面。在Login activity / presenter中,您可以添加浏览器历史事件处理程序,该处理程序检查上一个已知位置是否为null。如果为null,则将用户发送到#HOME页面。

您无需向浏览器询问用户访问过的应用中的哪些位置。如果您愿意,您可以记住每个会话的完整历史记录:ie [#HOME,#LOGIN,#FEATURES,#Home]。

答案 2 :(得分:0)

你有一个Queue<String> historyQueue;

第一次加载页面时,即onModuleLoad(),您可以Queue初始化。 捕获历史事件时,请检查其是后退还是新的历史记录标记。 如果是后退,则将其从队列中弹出,如果是新的,则将其添加到队列中。这样,取消按钮只是token = historyQueue.pop()并检查令牌是否为空。如果是,那就像你说的那样back = cancel,那么就做适当的事情。

相关问题