有时候,希望在页面访问之间保留滚动位置。Turbolinks 在加载数据后会重置滚动位置。如何禁用特定元素的此功能?
我的ES6解决方案:
const turbolinksPersistScroll = () => {
const persistScrollDataAttribute = 'turbolinks-persist-scroll'
let scrollPosition = null
let enabled = false
document.addEventListener('turbolinks:before-visit', (event) => {
if (enabled)
scrollPosition = window.scrollY
else
scrollPosition = null
enabled = false
})
document.addEventListener('turbolinks:load', (event) => {
const elements = document.querySelectorAll(`[data-${persistScrollDataAttribute}="true"]`)
for (let i = 0; i < elements.length; i++) {
elements[i].addEventListener('click', () => {
enabled = true
})
}
if (scrollPosition)
window.scrollTo(0, scrollPosition)
})
}
turbolinksPersistScroll()
在您想要保留滚动条位置的链接上添加data-turbolinks-persist-scroll=true
<a href="..." data-turbolinks-persist-scroll=true>链接</a>
这对我有效,也适用于link_to remote: true
。
turbolinks-disable-scroll
的元素。在加载之前,脚本保存滚动位置,在加载后加载保存的位置。// persist scrolls
// pirated from https://github.com/turbolinks/turbolinks-classic/issues/205
var elementsWithPersistentScrolls, persistentScrollsPositions;
elementsWithPersistentScrolls = ['.turbolinks-disable-scroll'];
persistentScrollsPositions = {};
$(document).on('turbolinks:before-visit', function() {
var i, len, results, selector;
persistentScrollsPositions = {};
results = [];
for (i = 0, len = elementsWithPersistentScrolls.length; i < len; i++) {
selector = elementsWithPersistentScrolls[i];
results.push(persistentScrollsPositions[selector] = $(selector).scrollTop());
}
return results;
});
$(document).on('turbolinks:load', function() {
var results, scrollTop, selector;
results = [];
for (selector in persistentScrollsPositions) {
scrollTop = persistentScrollsPositions[selector];
results.push($(selector).scrollTop(scrollTop));
}
return results;
});
const persistScrollDataAttribute = 'turbolinks-persist-scroll';
let scrollPosition = null;
const turbolinksPersistScroll = () => {
if (scrollPosition) {
window.scrollTo(0, scrollPosition);
scrollPosition = null;
}
const elements = document.querySelectorAll(`[data-${persistScrollDataAttribute}="true"]`)
for (let i = 0; i < elements.length; i++) {
elements[i].addEventListener('click', () => {
document.addEventListener("turbolinks:before-render", () => {
scrollPosition = window.scrollY;
}, {once: true})
})
}
}
document.addEventListener('turbolinks:load', turbolinksPersistScroll);
document.addEventListener('turbolinks:render', turbolinksPersistScroll);
看起来有两种方法可以解决这个问题。
第二种方法是我一直在寻找但无法找到的方法,因此我将在此提供我的答案。
这里的解决方案与第一种方法非常相似,但可能更简单。思路是在单击元素时获取正文的当前滚动位置,然后在加载页面后滚动到该位置:
Turbolinks.scroll = {}
$(document).on('click', '[data-turbolinks-scroll=false]', function(e){
Turbolinks.scroll['top'] = $('body').scrollTop();
})
$(document).on('page:load', function() {
if (Turbolinks.scroll['top']) {
$('body').scrollTop(Turbolinks.scroll['top']);
}
Turbolinks.scroll = {};
});
<a href='/' data-turbolinks-scroll='false'>Scroll preserving link</a>
Turbolinks
对象上使用了一个 scroll
属性来存储我的滚动位置,当点击一个 [data-turbolinks-scroll=false]
链接时,然后在我滚动页面后清除此属性。Turbolinks.scroll = {}
),否则,对非标记锚链接的后续单击将继续将您滚动到相同的位置。Turbolinks.scroll = {};
$(document).on('click', '[data-turbolinks-scroll=false]', function (e) {
Turbolinks.scroll['top'] = {
html: $("html").scrollTop(),
body: $("body").scrollTop()
}
});
$(document).on('turbolinks:load', function() {
if (Turbolinks.scroll['top']) {
$('html').scrollTop(Turbolinks.scroll['top']['html']);
$('body').scrollTop(Turbolinks.scroll['top']['body']);
}
Turbolinks.scroll = {};
});