【问题标题】:Prevent the URL from changing when popstate occurs防止出现 popstate 时更改 URL
【发布时间】:2018-01-03 15:28:05
【问题描述】:

您好,我正在尝试实现“您确定要离开此页面吗?”导航离开带有尚未提交的已修改表单的页面时弹出。该网站是使用自定义框架构建的单页应用程序。

由于所有锚链接都由框架处理,因此可以判断单击侧导航链接将导致页面更改并显示 Bootstrap 确认对话框。如果用户单击“确定”,则单击通过并进行 AJAX 调用以提取新页面内容。如果他们单击“取消”,则模式将被关闭并停留在当前页面上。

我无法解决的部分是用户在其网络浏览器中单击“返回”按钮时。这会触发“popstate”事件。由于它是一个单页应用程序,因此所有导航/历史记录都使用历史记录 API 进行管理。

问题是当有人点击“返回”时,由于“popstate”发生,URL 发生了变化,然后我显示“你确定要离开吗?”模态的。当事件发生时,您地址栏中的 URL 现在会显示您将从历史记录中转到的页面,而不是您当前正在查看的页面。如果您在引导程序中单击“取消”,请确认您现在在地址栏中显示错误的 URL。

event.preventDefault、event.stopPropagation 或在 popstate 中返回 false 不会阻止 URL 更改。 AFAIK 你不能在“popstate”之前拦截“Back”按钮。尝试在“popstate”中使用 window.history.replaceState 似乎也不起作用。

有没有人可以解决这个问题?

  1. 能否在“popstate”事件中阻止 URL 更改?
  2. 如果您确实决定希望它在模态被接受后通过,您能否以某种方式在“popstate”中重写历史以将 URL 更改回当前页面上的内容并保留先前的条目?李>
  3. 我没有想到的其他解决方案?

我最初的想法是阻止“popstate”中的 URL 更改,然后让框架触发链接单击以加载新内容并在他们单击“是”时更改 URL,但我还没有找到这样做的方法.

谢谢!

【问题讨论】:

  • 我能想到的就是给每个pushState添加一个自定义的状态变量,这样你就可以检测用户是前进还是后退,然后在用户选择时使用history.go()做反向取消。设置状态检测可能很棘手。

标签: javascript browser-history popstate


【解决方案1】:

我通过以下方式解决了这个问题;

  1. 每次创建历史状态时,我都会生成一个时间戳作为 guid
  2. 当前时间戳存储在顶层模块的变量中
  3. 当 popstate 发生时,传入的历史状态的 guid 会与顶级模块的 guid 进行比较
  4. 如果新的 guid 更大,我们会前进,如果新的 guid 更小,我们会后退
  5. 当用户单击后退/前进按钮时,哈希会更改为传入的 URL。如果用户单击取消,它将运行 history.go(direction),其中方向为 1 或 -1,具体取决于时间戳。这会将 URL 设置回应有的状态,并且不会对历史堆栈做任何奇怪的事情。顶级历史变量有一个标志,表明我们正在伪造页面更改,因此不会执行 popstate 中的链接加载逻辑。

唯一的怪癖是,如果用户在发送和返回请求并创建历史对象时单击“是”导航离开,则您不会更新顶级模块的 guid。如果您进行 guid 比较,您将始终认为您正在倒退,因为您刚刚添加的新事件将始终是最高数字。如果您不对历史 URL 发出新请求,这可能不是问题,但我们的框架会这样做,因此它不会像浏览器通常那样显示陈旧数据。

这并不理想,因为您确实看到了 URL 更改(没有内容更改),但到目前为止它似乎运行良好。我发现的另一个解决方案是将您自己网站的历史存储在本地/会话存储中并比较 URL,而不是使用 guid 时间戳来查找 popstate 方向。这在 Safari 的隐私浏览模式下不起作用,因为两个存储层都被禁用,所以我选择了 guid。

【讨论】:

    猜你喜欢
    • 2018-01-06
    • 2015-10-13
    • 1970-01-01
    • 2019-03-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-20
    • 2018-10-08
    相关资源
    最近更新 更多