【问题标题】:Prevent automatic browser scroll on refresh防止刷新时自动浏览器滚动
【发布时间】:2011-10-25 12:09:56
【问题描述】:

如果您转到页面 a 并滚动,然后刷新页面将在您离开的位置刷新。这很好,但是这也发生在 URL 中有锚点位置的页面上。例如,如果您单击链接http://example.com/post/244#comment5 并在环顾四周后刷新页面,您将不会处于锚点并且页面会跳来跳去。有没有办法用javascript来防止这种情况?这样无论您如何始终导航到锚点。

【问题讨论】:

  • 是 jQuery 解决方案好还是你想要纯 js?

标签: javascript browser


【解决方案1】:

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

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

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

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

【讨论】:

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

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

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

IE 不支持。 Browser compatibility.

【讨论】:

  • 如果它在 IE / Edge 中可用,这将是最好的答案。不过,您可以投票支持它在此处实施:wpdev.uservoice.com/forums/257854-microsoft-edge-developer/…
  • 这应该是 2019 年真正的正确答案。其他方法都不是 100% 有效的。
  • 可以确认这是最好的解决方案。此处的其他解决方案不适用于 Mobile Safari,并且可能会出现问题。这非常有效。
【解决方案3】:

在多次失败后,我终于成功了。 anzo 在这里是正确的,因为使用 beforeunload 将使页面在用户重新加载页面或单击链接时跳转到顶部。所以unload 显然是这样做的。

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

Javascript方式(感谢ProfNandaa):

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

编辑:2015 年 7 月 16 日

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

【讨论】:

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

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

基本上,如果使用锚点,我们将绑定到 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");
        });
    }

});

【讨论】:

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

这是一种更通用的方法。而不是试图阻止浏览器滚动(或像看起来那样跳到顶部),我只是恢复页面上的先前位置。 IE。我正在 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
}

【讨论】:

    【解决方案6】:

    这对我有用。

        //Reset scroll top
    
        history.scrollRestoration = "manual"
    
        $(window).on('beforeunload', function(){
              $(window).scrollTop(0);
        });
    

    【讨论】:

      【解决方案7】:

      你可以在最后加一个#,这样页面就会在顶部加载。

      适用于所有浏览器、移动设备和桌面,因为它非常简单。

      $(document).ready(function() {
      var url = window.location.href;
      console.log(url);
      if( url.indexOf('#') < 0 ) {
          window.location.replace(url + "#");
      } else {
          window.location.replace(url);
      }
      

      });

      // 这会加载以 # 结尾的页面。

      【讨论】:

      • 如果我直接在我的服务器上尝试这个,它就像魔术一样工作。但是,我的 cms 给了我标记错误。我不知道那是什么。
      • 如果您使用 wordpress,请将 $ 更改为 jQuery
      【解决方案8】:

      这绝对没问题。漂亮干净的javascript

          var objDiv = document.getElementById("chatbox");
      if ( window.history.replaceState ) {
        objDiv.scrollTop = objDiv.scrollHeight;
      
          window.history.replaceState( null, null, window.location.href );
      }
      

      【讨论】:

        【解决方案9】:

        你应该可以的。

        Onload,检查window.location.hash是否有值。如果是,则获取具有与哈希值匹配的 id 的元素。找到元素的位置(递归调用 offsetTop/offsetLeft),然后将这些值传递给window.scrollTo(x, y) 方法。

        这应该将页面滚动到所需的元素。

        【讨论】:

        • 这不会阻止浏览器进行自动滚动。这就是这个问题的意义所在。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-01-13
        • 1970-01-01
        • 2013-08-24
        • 2013-09-08
        • 1970-01-01
        • 2023-03-23
        相关资源
        最近更新 更多