如果您将此代码包含<script>
在 末尾的a 中<body>
,则您可能不需要侦听该turbolinks:load
事件。为什么?在第一次加载时,浏览器将能够查询位于脚本元素之前的任何元素。在 Turbolinks 加载脚本时,<body>
将可以访问页面上所有呈现的元素。
值得补充的是,通过调用document.addEventListener("turbolinks:load", …)
body<script>
元素,将在每次后续页面加载时调用侦听器,而不仅仅是在呈现脚本的页面上。如果
#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);
}
})();
请注意,这是未记录的,因此在未来的版本中可能不会公开提供。
最后,可能值得考虑将此代码段包含在您的主应用程序 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);
}
});