if ('scrollRestoration' in history) {
history.scrollRestoration = 'manual';
}
浏览器支持情况:
Chrome:支持(自版本46起)
Firefox:支持(自版本46起)
IE:不支持
Edge:支持(自版本79起)
Opera:支持(自版本33起)
Safari:支持
有关更多信息,请参见MDN上的浏览器兼容性.
history.scrollRestoration && history.scrollRestoration = 'manual';
或者甚至是 var sr = 'scrollRestoration'; history[sr] && history[sr] = 'manual';
- Bharata这是mozilla开发者核心一个已经超过一年的问题报告。不幸的是,这个问题没有得到很好的解决。我认为Chrome也是相同的情况: 没有可靠的方法通过js处理onpopstate
的滚动位置,因为它是本地浏览器行为。
但是,如果您查看HTML5历史规范,就会看到未来有希望,该规范明确希望在状态对象中表示滚动位置:
历史记录对象将其浏览上下文的会话历史记录表示为会话历史记录条目的平面列表。每个会话历史记录条目由URL和可选的状态对象组成,并且还可以具有标题、文档对象、表单数据、滚动位置和其他相关信息。
这些内容,以及上述mozilla票证上的评论,表明在不久的将来,至少对于使用pushState
的人来说,可能无法再通过onpopstate
恢复滚动位置。
不幸的是,在那之前,当使用pushState
时,滚动位置会被存储,而replaceState
不会替换滚动位置。否则,这将非常容易,并且您可以使用replaceState
在用户滚动页面时(带有谨慎的onscroll处理程序)设置当前滚动位置。
还不幸的是,HTML5规范没有指定何时必须触发popstate
事件,它只是说:“在导航到会话历史记录条目时,在某些情况下触发”,这并没有明确说明它是在之前还是之后;如果总是在之前,那么就可以处理在popstate之后发生的滚动事件的解决方案。
取消滚动事件?
此外,如果滚动事件是可取消的,那就会更容易,但事实上它是不可取消的。如果可以取消第一个滚动事件(用户的滚动事件像旅鼠一样成群结队,而由历史重新定位引发的滚动事件只有一个),那么一切都好办了。
目前没有解决方案
据我所知,现在唯一建议的方法是等待HTML5规范完全实施,并且跟随浏览器的行为,也就是说:当浏览器可以滚动时,通过动画滚动;当有历史事件时,让浏览器重新定位页面。在位置方面,您唯一能影响的是在页面定位良好时使用pushState
以便能回退至该位置。其他任何解决方案要么存在缺陷,要么太具体于某个浏览器,或者两者都有。
在这里,您需要使用某种可怕的浏览器嗅探技术。对于Firefox,我会采用您存储滚动位置并恢复它的解决方案。
根据您的描述,我认为我有一个基于Webkit的良好解决方案,但是我刚在Chrome 21中尝试了一下,似乎Chrome先滚动,然后触发popstate事件,然后再触发滚动事件。但是供参考,以下是我的解决方案:
function noScrollOnce(event) {
event.preventDefault();
document.removeEventListener('scroll', noScrollOnce);
}
window.onpopstate = function () {
document.addEventListener('scroll', noScrollOnce);
};
黑魔法,如通过移动absolute
定位元素来模拟页面滚动,由于屏幕重绘速度的限制而被排除。
因此,我99%确定答案是您无法实现,并且您将不得不使用问题中提到的其中一种妥协方案。两种浏览器在JavaScript知道有关它之前都会滚动,因此JavaScript只能在事件发生后做出反应。唯一的区别是Firefox直到Javascript触发后才绘制屏幕,这就是为什么Firefox有可行的解决方案,而WebKit没有的原因。
history.scrollRestoration = 'manual';
这应该可以防止浏览器滚动。目前只有Chrome 46及以上版本支持,但似乎Firefox也计划支持。
position: fixed
并将 top
指定为页面滚动位置。以下是一个示例:$(window).on('popstate', function()
{
$('.yourWrapAroundAllContent').css({
position: 'fixed',
top: -window.scrollY
});
requestAnimationFrame(function()
{
$('.yourWrapAroundAllContent').css({
position: 'static',
top: 0
});
});
});
是的,您会看到闪烁的滚动条,但这比其他问题要好一些。
//Listen for unload event. This is triggered when leaving the page.
//Reference: https://developer.mozilla.org/en-US/docs/Web/Events/unload
window.addEventListener('unload', function(e) {
//set scroll position to the top of the page.
window.scrollTo(0, 0);
});
将scrollRestoration设置为手动对我没有用,这是我的解决方案。
window.addEventListener('popstate', function(e) {
var scrollTop = document.body.scrollTop;
window.addEventListener('scroll', function(e) {
document.body.scrollTop = scrollTop;
});
});
document.body.scrollTop
已经被弃用了。这个可以用来代替:
document.documentElement.scrollTop
。 - Adam Jagosz这是我在一个需要滚动位置聚焦到特定元素的站点上实现的内容,当poststate被触发(后退按钮)时:
$(document).ready(function () {
if (window.history.pushState) {
//if push supported - push current page onto stack:
window.history.pushState(null, document.title, document.location.href);
}
//add handler:
$(window).on('popstate', PopStateHandler);
}
//fires when the back button is pressed:
function PopStateHandler(e) {
emnt= $('#elementID');
window.scrollTo(0, emnt.position().top);
alert('scrolling to position');
}
已在Firefox中测试并可正常工作。
Chrome会滚动到指定位置,但随后会重新定位回原始位置。
像其他人说的那样,没有真正的方法来做到这一点,只有丑陋的hacky方法。删除滚动事件监听器对我没有起作用,所以这是我的丑陋方法:
/// GLOBAL VARS ////////////////////////
var saveScrollPos = false;
var scrollPosSaved = window.pageYOffset;
////////////////////////////////////////
jQuery(document).ready(function($){
//// Go back with keyboard shortcuts ////
$(window).keydown(function(e){
var key = e.keyCode || e.charCode;
if((e.altKey && key == 37) || (e.altKey && key == 39) || key == 8)
saveScrollPos = false;
});
/////////////////////////////////////////
//// Go back with back button ////
$("html").bind("mouseout", function(){ saveScrollPos = false; });
//////////////////////////////////
$("html").bind("mousemove", function(){ saveScrollPos = true; });
$(window).scroll(function(){
if(saveScrollPos)
scrollPosSaved = window.pageYOffset;
else
window.scrollTo(0, scrollPosSaved);
});
});
它在Chrome、FF和IE中都可以工作(在IE中第一次返回时会闪烁)。欢迎提出任何改进建议!希望这有所帮助。
document.body.clientHeight
,但我没有看到它在所有浏览器中都能正常工作。 - Sean Hogan