我在一个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是建立在它之上的。
我已经实现了一个对话模式。popstate
事件是不可取消的,也不能被拦截以防止默认。(我想,否则开发者就可以阻止用户离开他们的网站了!)。
Turbolinks处理了所有的 popstate
事件,并有自己的机制来实现。你可以通过调用Turbolinks理解的方式推送到历史堆栈。
Turbolinks
.controller
.pushHistoryWithLocationAndRestorationIdentifier(<YOUR_LOCATION>, Turbolinks.uuid())
所以你可以通过调用: popstate
事件,Turbolinks 现在应该为你处理这个问题,将页面恢复到初始化对话框之前的状态。值得注意的是,虽然这是一个公开的方法,但它并没有被记录下来,因此可能在未来的版本中被删除。