2012-11-27 210 views
2

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

这里是我的情况(我认为这是非常标准):

我有了几个不同的页/地方的Web应用程序/位置(无论您想要调用它),我将显示这些位置以响应浏览器历史记录的更改。除了通常的“首页”,“功能”,“联系人”等大多是静态HTML页面之外,还有一个“用户”部分,用户可以登录他们的用户帐户(我们称之为)“项目”部分,用户可以在其中进行项目工作。

所以,现在我只需使用一个名为#Home#Features#Contact等,以及#User#工程才能到不同的页面本地链接。并且一切都很好,除了以下场景:

如果有人打开链接#项目,例如,该人员会显示一个项目登录对话框。此登录对话框有一个取消按钮,我希望通过简单地调用浏览器的返回按钮从我的应用程序(很简单)实现。我想这样做的原因,有两个方面:

  1. 你可以从在应用几个不同的位置,以及你的书签此登录对话框,并用这种方法,我就不需要跟踪用户来自哪里。
  2. 更重要的是:如果我不是没有记住用户从(如#Home)来和链接用户“前进”回到那个地方,我得到以下效果:
    • 比方说,用户访问#家庭,然后#功能,然后单击项目登录。
    • 如果用户点击取消按钮,我送他“前进”到#Features,在浏览器上的按钮,点击之后会带回的登录对话框,然后再次#Features最后#首页。不是你所期望的。
    • 相反,你会想回到#Home立即,只是你会得到什么,如果我简单地实现通过浏览器的后退功能取消

此时一切都很好,除了当用户通过直接书签链接到#工程最初进入这个登录对话框。因为如果我只是有取消 = 返回,用户将被从网页发回到他的浏览器的开始页面或他以前的任何位置。所以,在这种情况下,我确实需要链接“转发”到#家电

现在,我试图想几种方法来解决这个问题,并想出了一个解决方案夫妇的,但没有一个在我看来非常可取的,但让我反正分享他们或许炒作一些创造力:

  • 当页面第一次打开时,抓取历史令牌。如果是#工程#User或其他任何触发取消对话框,将下面的项目到历史堆栈:#Home#工程,其中最后一个是保存的初始令牌。那么,这可以让我取消按钮的功能正确......一旦...但是,如果用户点击事后,他将获得再次登录对话框(因为原来的历史令牌仍处于历史堆栈我不知道如何清除它)。点击取消然后会将他从页面中移除(不一致的行为)。
  • 我可以改为放置#+++#Home#工程到堆栈中,那么这将让我赶上点击,将通过检测需要用户在页面#+++链接,并简单地重新添加#主页令牌到堆栈上。这样就解决了问题,整体工作很漂亮,但我不喜欢的网站,不要让你背出他们不迅速锤击后退按钮足够了...
  • 最干净的解决办法是,如果我能以某种方式跟踪历史堆栈的长度与我应用中的位置有关。在开始时足够简单:它上面有一个项目。但是如果我得到这样的一系列地点:#家庭#特色#家庭?用户是否点击返回回到#家庭,即历史现在在浏览器中是长度1,或者他点击了#家庭链接,即历史是长度3?我检测,这将是想法:
    • 定义,即#Home相同#home
    • 使页面中的所有链接仅链接到链接的大写版本。
    • 每当您收到以 大写字母开头的历史更改通知时,请立即向历史记录添加两个项目,第一个以小写字母开头,第二个以大写字母开头。即#Home变成#Home#home#Home
    • 如果你有机会与一个小写字母开头的历史变化,你知道用户只需点击,而不是一个链接,你只需点击两次为他真正得到回上一页。
    • 现在您可以区分“后退”和“前进”链接,并在代码中保留精确的历史记录模型。
    • 但是,不幸的是,有两个问题:第一,浏览器历史杂乱无章(不是很优雅),第二,系统开始崩溃,如果用户点击足够快您的应用没有时间对消息做出反应。

看起来这应该是一个非常普遍的问题,我希望你们可以点我更有用的方向上比我的想法至今。

+1

您是否考虑过使用客户端路由系统(如angularjs提供的路由系统)? http://angularjs.org它可以使用html5的推送权益来跟踪后退和前进,并为您提供处理直接到达路线的客户的工具。 – SuitedSloth

+0

@thatjuan angularjs似乎功能非常丰富,可能需要一段时间才能筛选出来。你是否足够了解它在几句话中总结了与我的问题相关的部分?这将是非常有益的,谢谢。 –

+0

你看过活动和地方吗? https://developers.google.com/web-toolkit/doc/latest/DevGuideMvpActivitiesAndPlaces你试图发明自己的解决方案的任何理由? –

回答

1

window.history有一个length属性,该属性将显示当前选项卡的历史记录中有多少条目。不幸的是不是可过滤(所以没有办法说window.history.localURLs.length)。

如果您几乎完全在客户端(即部分更新,很少整页加载,使用哈希或API),那么您可能需要考虑将客户端路由框架合并到您的应用程序以避免重新发明车轮。

+0

好!这正是我期望的简单细节,它可以帮助我解决这个问题。现在,我需要做的只是在页面第一次加载时存储history.length,然后让我的“后退”功能检查是否有东西要回去,如果没有,请将它变成“主页”链接!甜!谢谢!我很惊讶GWT不公开这个。它完全跨浏览器吗?我现在就试试。 –

+1

ARGH!它几乎可以工作!除了它返回的历史长度不仅仅是我仍然可以点击“返回”的次数,还包括了我可以点击“前进”的次数!因此,它不再工作...是否有一个等价物只返回“后退”计数? –

+0

@Markus - 不幸的是,没有。 –

0

你怎么样有一个Queue<String> historyQueue;

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

+0

这将是一个很好的解决方案,除了两个问题:不幸的是,我不认为有一种可靠的方法来检测页面更改是“前进”还是“后退”更改。而且,更糟糕的是,如果这是可能的话,那么您可能无法正确处理许多浏览器在历史中随机跳转的能力。 –

1

在用户可以访问#LOGIN对话框之前,将执行入口点类。在这堂课你可以记住最后一个已知的页面。在登录活动/演示者中,您可以添加浏览器历史记录事件处理程序,该处理程序会检查最后一个已知位置是否为空。如果为null,则将用户发送到#HOME页面。

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

+0

如果用户使用浏览器的历史记录按钮随机浏览,我该如何确保正确记住历史记录?我所能做的就是保持自己的历史,即假设每一步都是“前进”的举动。因此,如果用户点击“主页”,“功能”,返回,那么我的历史记录现在将包含“主页”,“功能”,“主页”,浏览器的历史记录是否仅包含“主页”。不知道我明白我该如何使用它来做出关于如何处理对话取消点击的决定? –

+1

在你原来的问题中,你描述了一个非常具体的问题:回到另一个网站。您只需要知道您自己的历史记录是否为空即可解决该问题。除此之外,让浏览器管理历史。 –

+0

不幸的是,这并不能提供给我这些信息。我永远无法分辨用户是否回到“空”状态。假设我看到页面转换“Home”,“Features”,“Home”(从上面)。用户现在是否处于BACK将我带离页面的位置?或回到“功能”?即通过单击“返回”或“功能”页面上的链接或其他书签的某个位置,他是否可以访问第二个“主页”?这是我需要解决的细节。 –