2

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

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

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

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

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

有没有人有关于如何使这项工作的解决方案?

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

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

谢谢!

4

1 回答 1

0

我通过执行以下操作解决了这个问题;

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

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

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

于 2018-01-04T20:26:58.580 回答