使用 turbolinks 以编程方式打开 Bootstrap 选项卡
Open Bootstrap tab programmatically with turbolinks
我正在尝试在页面加载后打开 Bootstrap 4 选项卡。如果我刷新页面它确实有效,但如果我在站点内导航,我会收到查询 select 或空错误。
这是我的代码,基本上是我对这个 https://webdesign.tutsplus.com/tutorials/how-to-add-deep-linking-to-the-bootstrap-4-tabs-component--cms-31180 做的移植,因为我使用的是 Bootstrap-native,所以我不得不用 vanilla Javascript 重写它。
document.addEventListener("turbolinks:load", 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);
}
});
我把它放在结束正文标签之前。如果我写 http://www.myURL#mytab
并单击刷新,页面刷新和选项卡被更改,但如果我从 (turbo)link 到达那里,它找不到要查询的选项卡 select .恐怕问题出在 "load" 事件上,我尝试了不同的方法,但无法正常工作。
如果您将此代码包含在 <body>
末尾的 <script>
中,您可能不需要侦听 turbolinks:load
事件。 为什么? 在第一次加载时,浏览器将能够查询位于脚本元素之前的任何元素。 <body>
中的 Turbolinks 加载脚本将有权访问页面上的所有渲染元素。
值得补充的是,通过在正文 <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 管理它自己的已访问页面缓存,因此当用户点击 "Back" 时,页面将从该缓存中呈现。为此,它有一个用于添加到浏览器自己的 history
堆栈的系统。如果您绕过 Turbolinks 系统,自己调用 history.replaceState
(或 history.pushState
),那么您最终可能会破坏 "Back" 导航。 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);
}
});
我正在尝试在页面加载后打开 Bootstrap 4 选项卡。如果我刷新页面它确实有效,但如果我在站点内导航,我会收到查询 select 或空错误。
这是我的代码,基本上是我对这个 https://webdesign.tutsplus.com/tutorials/how-to-add-deep-linking-to-the-bootstrap-4-tabs-component--cms-31180 做的移植,因为我使用的是 Bootstrap-native,所以我不得不用 vanilla Javascript 重写它。
document.addEventListener("turbolinks:load", 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);
}
});
我把它放在结束正文标签之前。如果我写 http://www.myURL#mytab
并单击刷新,页面刷新和选项卡被更改,但如果我从 (turbo)link 到达那里,它找不到要查询的选项卡 select .恐怕问题出在 "load" 事件上,我尝试了不同的方法,但无法正常工作。
如果您将此代码包含在 <body>
末尾的 <script>
中,您可能不需要侦听 turbolinks:load
事件。 为什么? 在第一次加载时,浏览器将能够查询位于脚本元素之前的任何元素。 <body>
中的 Turbolinks 加载脚本将有权访问页面上的所有渲染元素。
值得补充的是,通过在正文 <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 管理它自己的已访问页面缓存,因此当用户点击 "Back" 时,页面将从该缓存中呈现。为此,它有一个用于添加到浏览器自己的 history
堆栈的系统。如果您绕过 Turbolinks 系统,自己调用 history.replaceState
(或 history.pushState
),那么您最终可能会破坏 "Back" 导航。 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);
}
});