防止浏览器在刷新时自动滚动

IT技术 javascript browser
2021-02-02 05:42:56

如果您转到页面 a 并四处滚动,则刷新页面将在您离开它的位置刷新。这很好,但是这也发生在 url 中有锚位置的页面上。一个例子是,如果你点击一个链接http://example.com/post/244#comment5并在环顾四周后刷新页面,你就不会在锚点处,页面会跳来跳去。有没有办法用javascript防止这种情况?因此,无论您做什么,您都将始终导航到锚点。

6个回答

在 Chrome 上,即使您将 scrollTop 强制为 0,它也会在第一个滚动事件之后跳转。

你应该将滚动绑定到这个:

$(window).on('beforeunload', function() {
    $(window).scrollTop(0);
});

所以浏览器被欺骗相信它在刷新之前的开始。

在 Chrome 36、Firefox 30 和 IE 11 上测试。效果很好!
2021-03-19 05:42:56
为什么选择“beforeunload”事件而不是“unload”。我的测试表明,最后一个允许避免在页面被浏览器真正卸载之前跳转到顶部。
2021-03-21 05:42:56
对于非 jQuery 实现: window.onbeforeunload = function(){ window.scrollTo(0,0); }
2021-03-24 05:42:56
如果您不想弄乱滚动,那么比接受的答案更有用。
2021-03-29 05:42:56
这在 Chrome 33 中不起作用。我的意思是它确实在加载新页面之前滚动到顶部。然而浏览器仍然以某种方式记住之前的滚动位置并执行相同的自动滚动到该位置。
2021-03-30 05:42:56

要禁用自动滚动恢复,只需将此标签添加到 head 部分。

<script>history.scrollRestoration = "manual"</script>

IE 不支持。浏览器兼容性。

如果它在 IE/Edge 中可用,这将是最好的答案。你可以投票支持它在这里实施:wpdev.uservoice.com/forums/257854-microsoft-edge-developer/...
2021-03-22 05:42:56
这应该是 2019 年真正的正确答案。其他方法都不是 100% 有效的。
2021-04-08 05:42:56
可以确认这是最好的解决方案。此处的其他解决方案不适用于 Mobile Safari,并且可能会出现问题。这完美地工作。
2021-04-11 05:42:56

经过多次失败,我终于成功了。anzo在这里是正确的,因为beforeunload当用户重新加载页面或单击链接时,使用将使页面跳转到顶部。这样unload做的明确方法也是如此。

$(window).on('unload', function() {
   $(window).scrollTop(0);
});

Javascript 方式(感谢ProfNandaa):

window.onunload = function(){ window.scrollTo(0,0); }

编辑:16/07/2015

即使有unload事件,Firefox 仍然存在跳转问题

@TelvinNguyen 你能提供任何资源吗?我在 google chrome 72 上对此进行了测试,但对我来说仍然可以正常工作。
2021-03-21 05:42:56
此解决方案比beforeunload解决方案好得多,因为它可以防止在重新加载和锚点点击时跳转到页面顶部。
2021-03-28 05:42:56
@JanakaDombawela 我所说的:移动会导致问题的新标签是不正确的。但是,您可以看到此示例中的 onunload 事件没有正确触发,即使使用 jQuery 1.9.1 与 jQuery 1.8.3。onunload 是不可靠的。jsfiddle.net/6s4jhdug/3 (1.8.3) jsfiddle.net/frt45ue9 (1.9.1)
2021-04-05 05:42:56
@BradGreens 对于现代 Chrome,当用户切换到其他选项卡时,也会触发 onunload 事件,这是出乎意料的。onbeforeunload 仍然是有效的解决方法。
2021-04-12 05:42:56

由于浏览器行为的变化,不再推荐此解决方案。查看其他答案。

基本上,如果使用锚点,我们将绑定到 windows 滚动事件。这个想法是第一个滚动事件必须属于浏览器完成的自动重新定位。发生这种情况时,我们会自行重新定位,然后移除绑定事件。这可以防止后续页面滚动使系统崩溃。

$(document).ready(function() {
    if (window.location.hash) { 
        //bind to scroll function
        $(document).scroll( function() {
            var hash = window.location.hash
            var hashName = hash.substring(1, hash.length);
            var element;

            //if element has this id then scroll to it
            if ($(hash).length != 0) {
                element = $(hash);
            }
            //catch cases of links that use anchor name
            else if ($('a[name="' + hashName + '"]').length != 0)
            {
                //just use the first one in case there are multiples
                element = $('a[name="' + hashName + '"]:first');
            }

            //if we have a target then go to it
            if (element != undefined) {
                window.scrollTo(0, element.position().top);
            }
            //unbind the scroll event
            $(document).unbind("scroll");
        });
    }

});
最初,我在一个小的基本示例文件中使用它来检查它。一旦我确认它确实有效,我就对它在我的项目中如何不起作用感到困惑。通过消除过程,我设法在我的 css 文件中找到了一个导致它出错的样式声明。这是外部字体的应用。我将您的代码包装在一个函数中,现在将它传递到 doc.ready 处理程序中的 $(window).load() 处理程序中。它现在可以工作了(初始页面有轻微的闪烁)。感谢您的代码!让我知道这是否是一个可靠的修复。
2021-03-27 05:42:56
@FlashThunder - 你能定义“不起作用”吗?发布控制台消息?
2021-04-02 05:42:56
如果您的内容在页面加载后加载,它将不起作用;例如:有 2 个 div,将从 ajax 填充横幅。
2021-04-06 05:42:56
嘘!这是一个有趣的深夜问题。我告诉我的老板,我在办公桌前睡着了是你的错。我只是做了一个快速更改以删除 return 语句。这干扰了我为滚动事件添加的解除绑定。
2021-04-12 05:42:56
我认为应该考虑的一个用例是用户是否在自动滚动发生之前滚动页面。我记得自动滚动只在页面完全加载后发生。如果用户在之前滚动,则取消自动滚动。因此,您需要某种方式来区分用户启动的滚动和浏览器启动。我不知道该怎么做,但我记得这是可能的。
2021-04-14 05:42:56

这是一种更通用的方法。我没有试图阻止浏览器滚动(或像看起来那样跳到顶部),而是恢复页面上的先前位置。即,我正在 localStorage 中记录页面的当前 y 偏移,并在页面加载后滚动到该位置。

function storePagePosition() {
  var page_y = window.pageYOffset;
  localStorage.setItem("page_y", page_y);
}


window.addEventListener("scroll", storePagePosition);


var currentPageY;

try {
  currentPageY = localStorage.getItem("page_y");

  if (currentPageY === undefined) {
    localStorage.setItem("page_y") = 0;
  }

  window.scrollTo( 0, currentPageY );
} catch (e) {
    // no localStorage available
}