Turbolinks 5和历史上的popstate事件

问题描述 投票:0回答:1

我在一个Rails 6.1的web应用中使用Turbolinks。

我知道Turbolinks使用AJAX来代替了之前的 body 并使用 history.pushState() 来更新URL以匹配。

我已经实现了一个对话模式系统,它将一个元素添加到了 body 然后使用CSS和一些事件处理程序来显示该元素,当用户点击对话框上的关闭按钮时,关闭对话框并将其删除。

问题是在移动设备浏览器上,用户更喜欢使用后退按钮(Android上的左下角箭头),而不是伸手到对话框顶部点击关闭按钮。

所以我需要一种方法来拦截正常的Turbolinks。restoration 事件,并执行一些我自己的Javascript在 popstate 事件,而不是由Turbolinks接管。

我知道Turbolinks的文档中写道 restoration 事件不能被取消,但我在寻找一种方法,我可以使用本地JS来拦截 popstate 在Turbolinks得到它之前,我想它应该很简单:当我在Javascript中显示一个对话框时,我执行了一个对话框。

我想这应该是很直接的:当我在Javascript中显示一个对话框时,我会执行

window
      .history
      .pushState({ dialog: { id: "id-of-dialog" } }, null, window.location)

的事件处理程序,然后为 popstate 关闭对话框。

document.addEventListener("popstate", (event) => {
  console.log(event.state)
  if (event.state.dialog) {
    const dialogId = event.state.dialog.id
    const dialogElement = document.getElementyById(dialogId)

    // Note: I do have some animations for closing, so the closing logic is slightly more
    // complex than this, but this shows the gist of what's going on.
    dialogElement.classList.remove("dialog-container-open")
    dialogElement.remove()

    // Does this stop Turbolinks from taking over?
    event.preventDefault()
    event.stopPropagation()
  } else {
    // Do nothing, let Turbolinks handle it
  }
})

然而,在 popstate 事件,Turbolinks总是在历史堆栈的顶部有一个状态,我不知道它是如何发生的,也不知道它在哪里发生,因此我无法阻止它。

从本质上讲,我只是想手动管理历史记录。popstate 的逻辑来处理我的对话框。但是无论如何,当我只是想关闭一个对话框时,Turbolinks似乎总是会启动并刷新页面。

有什么方法可以实现这个问题吗? 我试过 hashchange 也是,但 history API似乎更有前途,因为Turbolinks是建立在它之上的。

javascript turbolinks pushstate html5-history
1个回答
0
投票

我已经实现了一个对话模式。popstate 事件是不可取消的,也不能被拦截以防止默认。(我想,否则开发者就可以阻止用户离开他们的网站了!)。

Turbolinks处理了所有的 popstate 事件,并有自己的机制来实现。你可以通过调用Turbolinks理解的方式推送到历史堆栈。

Turbolinks
  .controller
  .pushHistoryWithLocationAndRestorationIdentifier(<YOUR_LOCATION>, Turbolinks.uuid())

所以你可以通过调用: popstate 事件,Turbolinks 现在应该为你处理这个问题,将页面恢复到初始化对话框之前的状态。值得注意的是,虽然这是一个公开的方法,但它并没有被记录下来,因此可能在未来的版本中被删除。

© www.soinside.com 2019 - 2024. All rights reserved.