我正在尝试找到一个干净的解决方案,以最有效的方式处理浏览器历史记录。(我正在使用 GWT,但这个问题确实比这更笼统。)
这是我的情况(我认为这很标准):
我有一个 Web 应用程序,它有几个不同的页面/地点/位置(无论你想怎么称呼它),我会根据浏览器历史记录的更改显示这些应用程序。除了通常是静态 HTML 页面的“主页”、“功能”、“联系人”等之外,还有一个“用户”部分,人们可以在其中登录他们的用户帐户和(我们称之为)“项目”部分,用户可以在其中处理他们的项目。
所以,现在我只需使用名为#Home、#Features、#Contact等的本地链接以及#User、#Project来访问不同的页面。一切都很好,除了以下情况:
例如,如果有人打开链接#Project,则会向该人显示项目登录对话框。这个登录对话框有一个cancel按钮,我想通过back从我的应用程序中调用浏览器的按钮来实现它(很简单)。我想这样做的原因有两个:
- 您可以从应用程序中的几个不同位置以及您的书签访问此登录对话框,使用这种方法,我不需要跟踪用户来自哪里。
- 更重要的是:如果我确实记得用户来自哪里(例如#Home)并将用户“转发”链接到那个地方,我会得到以下效果:
- 假设用户访问#Home,然后是#Features,然后单击项目登录。
- 如果用户单击cancel按钮,我将他“转发”到#Features,然后单击浏览器的back按钮将返回登录对话框,然后再次返回#Features,最后返回 #Home。不是你所期望的。
- 相反,您希望立即返回#Home,这正是我cancel通过浏览器的返回功能实现的结果。
此时一切都很好,除非用户最初通过指向#Project的直接书签链接进入此登录对话框。因为那时,如果我只是有cancel= back,用户就会从页面完全返回到他的浏览器的起始页面或他之前所在的任何地方。因此,在这种情况下,我确实需要将“转发”链接到#Home。
现在,我尝试了几种方法来解决这个问题,并提出了一些解决方案,但似乎没有一个对我来说是非常可取的,但还是让我分享它们以激发一些创造力:
- 首次打开页面时,获取历史令牌。如果是#Project或#User或其他任何触发可取消对话框的项目,请将以下项目放入历史堆栈:#Home、#Project,其中最后一项是保存的初始令牌。然后,这允许我的cancel按钮正常工作......一次......但是,如果用户back随后点击,他将再次获得登录对话框(因为原始历史令牌仍在历史堆栈中,我不知道如何清除它)。然后单击cancel将使他离开页面(不一致的行为)。
- 我可以改为将#+++、#Home、#Project放到堆栈上,然后我可以back通过检测#+++链接并简单地重新添加#归入堆栈的令牌。这将解决问题并且总体上工作得很好,除了我讨厌那些不让你在没有足够快地敲击后退按钮的情况下让你退出它们的网站......
- 最干净的解决方案是,就我的应用程序中的位置而言,如果我能以某种方式跟踪历史堆栈的长度。一开始很容易:它上面有一个项目。但是,如果我得到一系列这样的地方:#Home、 # Features、#Home?用户是否点击back返回#Home,即浏览器中的历史现在长度为1,或者他是否点击了#Home链接,即历史长度为3?我检测这一点的想法是:
- 定义, # Home与#home相同。
- 让页面中的所有链接仅链接到大写版本的链接。
- 每当您收到以大写字母开头的历史更改通知时,立即向历史添加两个项目,第一个以小写字母开头,第二个也以大写字母开头。即#Home变成了#Home、#home、#Home。
- 如果您曾经收到以小写字母开头的历史记录更改,您知道用户只是单击back而不是链接,您只需再单击back两次,他就可以真正返回到前一页。
- 现在您可以区分“向后”和“向前”链接,并在代码中维护准确的历史模型。
- 但是,不幸的是,这有两个问题:第一,浏览器历史记录变得混乱(不是很优雅),第二,系统开始崩溃,如果用户点击back得足够快以至于你的应用程序没有有时间对消息做出反应。
看起来这应该是一个非常普遍的问题,我希望你们中的一个人可以为我指出一个比我迄今为止的想法更有用的方向。