如果您将此代码包含在<body> 末尾的<script> 中,您可能不需要监听turbolinks:load 事件。 为什么?在第一次加载时,浏览器将能够查询位于脚本元素之前的任何元素。在 Turbolinks 加载脚本时,<body> 将有权访问页面上所有呈现的元素。
值得补充的是,通过在主体<script> 元素中调用document.addEventListener("turbolinks:load", …),侦听器将在每次 后续页面加载时被调用,而不仅仅是在呈现脚本的页面上。如果
#nav-tab 元素在后续页面加载时不存在,然后您将看到 querySelector 错误。更重要的是,如果你在不止一个页面上包含脚本,那么监听器会一次又一次地重复,这可能不是你想要的!
因此,解决问题的第一步是删除事件侦听器。我们会将您的代码包装在一个立即调用的函数中,以防止污染全局范围:
;(function() {
let url = location.href.replace(/\/$/, "");
if (location.hash) {
const hash = url.split("#");
document.querySelector('#nav-tab a[href="#'+hash[1]+'"]').Tab.show();
url = location.href.replace(/\/#/, "#");
history.replaceState(null, null, url);
setTimeout(() => {
window.scrollTo(0,0);
}, 400);
}
})();
接下来要知道的是,Turbolinks 管理自己的已访问页面缓存,因此当用户点击“返回”时,会从该缓存中呈现页面。为此,它有一个用于添加到浏览器自己的history 堆栈的系统。如果您绕过 Turbolinks 系统并自己致电history.replaceState(或history.pushState),那么您最终可能会破坏“返回”导航。 Turbolinks 没有手动添加到其历史堆栈的记录方法,但您可以尝试以下方法:
;(function() {
let url = location.href.replace(/\/$/, "");
if (location.hash) {
const hash = url.split("#");
document.querySelector('#nav-tab a[href="#'+hash[1]+'"]').Tab.show();
url = location.href.replace(/\/#/, "#");
Turbolinks
.controller
.replaceHistoryWithLocationAndRestorationIdentifier(url, Turbolinks.uuid())
setTimeout(() => {
window.scrollTo(0,0);
}, 400);
}
})();
请注意,这是未记录的,因此可能不会在未来的版本中公开提供。
最后,可能值得考虑将这个 sn-p 包含在您的主应用程序 JavaScript 包中,并将其加载到 <head> 而不是正文中。在这种情况下,您将需要使用 `turbolinks:load 处理程序。它可能看起来像:
document.addEventListener('turbolinks:load', function () {
let url = location.href.replace(/\/$/, "");
const hash = url.split("#");
const navLink = document.querySelector('#nav-tab a[href="#'+hash[1]+'"]')
if (location.hash && navLink) {
navLink.Tab.show();
url = location.href.replace(/\/#/, "#");
Turbolinks
.controller
.replaceHistoryWithLocationAndRestorationIdentifier(url, Turbolinks.uuid())
setTimeout(() => {
window.scrollTo(0,0);
}, 400);
}
});