【问题标题】:How distinguish between browser back and user manually changing location hash如何区分浏览器返回和用户手动更改位置哈希
【发布时间】:2016-05-31 19:20:30
【问题描述】:

问题

鉴于从/page.html#A/page.html#B 的导航,有没有办法区分用户:

  1. 单击浏览器的“返回”按钮,然后
  2. 手动将网址改回/page.html#A

背景/上下文

我正在构建一个网络应用程序,其中单个页面在多张内容幻灯片之间转换,每张幻灯片都由特定的位置哈希标识,例如'#A''#B'

例如,当用户在幻灯片“A”上并选择选项“B”时,位置从/page.html#A 更改为/page.html#B

转换后,location.hash==#Bback()(通过 JS 或浏览器按钮)会将用户返回到 location.hash==#A

但是,没有什么可以阻止用户手动更改 URL 栏中的哈希值。在这种情况下,浏览器会认为这是向前导航,在后面的历史记录中插入/page.html#B。也就是说,导航历史记录将是 #A > #B > #A,点击返回现在会将用户带到 #B

我需要区分这两种情况,这样当我知道用户手动更新了url hash时,我可以触发go(N)同步浏览器返回/下一个状态。

目前的尝试

1) HTML5 popstate 事件:
我曾希望 html5 popstate 事件 (https://developer.mozilla.org/en-US/docs/Web/Events/popstate) 只会在 case#1 中触发,但我可以确认它在两种情况下都会触发。

2) 浏览器.onhashchange 事件
我可以确认,如果存在,则在两种情况下都会触发该事件

3) jQuery 移动版hashChange() 我可以确认在这两种情况下都被解雇了

4) 读取浏览器导航历史
我的下一个想法是维护一个哈希历史的JS数组,并比较新的哈希和浏览器历史是否与JS数组匹配,但是出于安全原因,JS无法读取浏览器位置历史。

想法

我知道,如果我调用 window.history.forward(),但没有页面存在,则什么也不会发生。我正在考虑一个 JS 哈希历史数组,调用 forward(),检查新的 location.hash(现在安全允许它),与 JS 数组进行比较,然后调用 go(N) 以同步浏览器返回/下一个状态。但是有点乱。

【问题讨论】:

    标签: javascript browser hash back-button browser-history


    【解决方案1】:

    是的,你可以区分:

    1. 点击back()/forward()浏览器按钮,然后
    2. 在浏览器网址栏中手动编辑location.hash

    也可以将两者与页内 HTML 元素导航一起使用。

    问题:

    1. 浏览器back()forward()go() 调用不会立即更新location.hash。通过setTimeout() 需要等待~10ms 让浏览器完成导航并更新location

    解决方案(伪代码):

    • 维护backward_history_hashes 的数组(注意“向后”是指逻辑上的,而不是时间上的)
    • 保持current_location.hash的值
    • 维护forward_history_hashes的数组
    • in-page导航维护一个布尔标志,默认为FALSE
    • 维护一个布尔标志是否为ignore_hash_change
    • 创建一个setTimeout() 监视器来检查 location.hash 的变化

    在每种情况下,历史数组都是location.hashes 的简单字符串数组

    on_in_page_navigation()

    • 设置in_page_flag = true
    • 通过back()forward()go(N) 触发浏览器导航
    • 设置in_page_flag = false

    on_location_hash_change()

    • 设置ignore_hash_change = true
    • 如果(! in_page_flagrewrite_browser_history()
    • 显示新location.hash对应的内容
    • 设置ignore_hash_change = false

    rewrite_browser_history()

    • 假设它是手动 URL 编辑,并使用 JS 历史数组来触发 back()forward() 调用以生成所需的浏览器历史
    • go(N) 执行到所需的location.hash 以将浏览器历史与JS 历史数组同步

    【讨论】:

      【解决方案2】:

      由于 javascript 中没有后退按钮事件,我可以推荐的最好方法是在您的页面上创建自己的后退按钮

      看:How to Detect Browser Back Button event - Cross Browser

      【讨论】:

      • 我可以确认这不能区分这两种情况。在这两种情况下,无论用户单击“返回”,还是手动更改 url 中的哈希值,都会触发 jQuery 的“hashchange”事件。
      • 在 (1) 单击后退按钮,(2) 用户手动更改 URL 的情况下,您想实现什么?
      • 每个哈希代表一个表单。考虑用户从 [A>B>C] 导航的情况。在情况(1)中,单击“返回”会将用户带到#B,并且浏览器状态为 [A>B],这是正确的。在情况(2)中,用户输入#B,浏览器历史变成[A>B>C>B]。现在,如果用户单击“返回”,他们会转到#C 而不是#A。这很重要,因为只有一个路径子集是有效的,例如 valid=[ABC, ACD, AD],所有其他路径都需要规范化。如果我可以检测到 case(2),我可以得到重复项之间的距离,例如 [A>B>C>B],(Bs 之间的距离 = 2),然后执行 go(-3) + hash=B 以生成浏览器历史记录[A>B]
      • 你引用的新文章的问题是它仍然不能区分大小写(1)和(2)。它仅区分浏览器操作和页内操作。我正在开发的应用程序已经很好地处理了页面内操作,根据用户操作,使用对 back()、forward() 或 location.hash 的简单调用。似乎可以通过维护历史数组来通过程序派生来区分 case(1) 和 (2)。几天后我会发布一个可能的解决方案,除非其他人在此期间有更快的解决方案。
      猜你喜欢
      • 2011-07-21
      • 1970-01-01
      • 1970-01-01
      • 2015-03-15
      • 1970-01-01
      • 2013-11-01
      • 1970-01-01
      • 2013-07-03
      • 2012-08-30
      相关资源
      最近更新 更多