加载页面时如何禁用锚点“跳转”?

Posted

技术标签:

【中文标题】加载页面时如何禁用锚点“跳转”?【英文标题】:How to disable anchor "jump" when loading a page? 【发布时间】:2011-04-09 05:07:55 【问题描述】:

我认为这可能是不可能的,我会尽力解释。 我有一个包含选项卡的页面(由 jquery 驱动),由以下内容控制:

我正在使用此代码,由上一个问题中的另一个用户提供。

<script type="text/javascript">
    $(function() 

     $('html, body').animate(scrollTop:0); // this is my "fix"

        var tabContent = $(".tab_content");
        var tabs = $("#menu li");
        var hash = window.location.hash;
     tabContent.not(hash).hide();
        if(hash=="") 
      $('#tab1').fadeIn();
     
        tabs.find('[href=' + hash + ']').parent().addClass('active');

        tabs.click(function() 
            $(this).addClass('active').siblings().removeClass('active');
            tabContent.hide();
            var activeTab = $(this).find("a").attr("href");

            $(activeTab).fadeIn();
           return false;
        );

    );
</script>

当我直接访问“标签”页面时,这段代码效果很好。

但是,我需要链接到其他页面的各个选项卡 - 为此,代码获取 window.location.hash 然后显示相应的选项卡。

页面不会因为“return false”而“跳转”到锚点。

但是,此事件仅在单击事件时触发。因此,如果我从任何其他页面访问我的“标签”,就会触发“跳转”效果。为了解决这个问题,我自动滚动到页面顶部,但我宁愿这没有发生。

有没有办法在页面加载时模拟“return false”,防止出现锚点“跳转”。

希望这已经足够清楚了。

谢谢

【问题讨论】:

【参考方案1】:

你的修复不起作用吗?我不确定我是否正确理解了这个问题 - 你有演示页面吗?你可以试试:

if (location.hash) 
  setTimeout(function() 

    window.scrollTo(0, 0);
  , 1);

编辑:经过测试并在 Windows 上的 Firefox、IE 和 Chrome 中运行。 编辑 2:将 setTimeout() 移动到 if 块内,道具 @vsync。

【讨论】:

英雄!是的,我的“修复”确实有效,但是页面会“滚动”(正如我的代码告诉它的那样),我宁愿它不滚动。您的代码完美运行。我没有看过 ScrollTo - 这个功能甚至是必要的吗?它似乎只用 window.scrollTo(0, 0); 我在没有setTimeout 的空白页面上的 Firefox 中尝试了它,但它并不总是有效。如果它在 jQuery 的 $(function() 中,你可能不需要它。你并不真的需要location.hash,但是把它留在里面很好,所以浏览器可能不需要做任何事情。还会提醒您 scrollTo 的用途! 今天我遇到了同样的问题。我实际上必须将哈希(与选项卡名称/href 值相同)添加到我的导航链接。我最终在我的选项卡中添加了一个 1-char 后缀,然后在将它们与 window.location.hash 进行比较时将值按 1 char (str.slice(0,-1) . if 应该在外面,而不是在里面。此外,间隔的最小值约为 10,因此 0 或 1 与 10 相同,具体取决于浏览器。 这不会阻止浏览器跳转到主题标签,您必须放置一个空的主题标签以防止“跳跃”,请参阅我的答案***.com/a/29823913/826194【参考方案2】:

在这里查看我的答案:*** Answer

诀窍是尽快删除主题标签并将其值存储起来供自己使用:

重要的是不要将这部分代码放在 $() 或 $(window).load() 函数中,因为这为时已晚,并且浏览器已经移动到标签。

// store the hash (DON'T put this code inside the $() function, it has to be executed 
// right away before the browser can start scrolling!
var target = window.location.hash,
    target = target.replace('#', '');

// delete hash so the page won't scroll to it
window.location.hash = "";

// now whenever you are ready do whatever you want
// (in this case I use jQuery to scroll to the tag after the page has loaded)
$(window).on('load', function() 
    if (target) 
        $('html, body').animate(
            scrollTop: $("#" + target).offset().top
        , 700, 'swing', function () );
    
);

【讨论】:

我遇到了一个 FF 的错误,我在一个非常长的列表的 div 上使用 max-height overflow-y,FF 会向下滚动隐藏节点在 dom 中的位置。这仅使用了前三行实际代码(不是 cmets),这更正了我的 FireFox 问题。 这正是我想要的。对其进行了一些修改以满足我的需要,但比滚动回顶部更好的解决方案。【参考方案3】:

还有其他方法可以跟踪您所在的标签;可能会设置一个 cookie,或者在隐藏字段中设置一个值,等等。

我想说,如果您不希望页面在加载时跳转,最好使用这些其他选项之一而不是哈希,因为优先使用哈希的主要原因是允许正是您想要阻止的内容。

另一点 - 如果您的哈希链接与文档中的标签名称不匹配,则页面不会跳转,因此如果您想继续使用哈希,您可以操纵内容以便命名标签不同。如果你使用一致的前缀,你仍然可以使用 Javascript 在它们之间跳转。

希望对您有所帮助。

【讨论】:

好点。不要忘记尝试在关闭 JS/CSS 的情况下保持页面可用/可访问。【参考方案4】:

我使用了 dave1010 的解决方案,但是当我将它放在 $().ready 函数中时,它有点跳动。所以我这样做了:(不在 $().ready 里面)

    if (location.hash)                // do the test straight away
        window.scrollTo(0, 0);         // execute it straight away
        setTimeout(function() 
            window.scrollTo(0, 0);     // run it a bit later also for browser compatibility
        , 1);
    

【讨论】:

【参考方案5】:

    如果地址中有http://site.com/#abc 哈希并且id="abc" 的元素可见,浏览器会跳转到&lt;element id="abc" /&gt;。因此,您应该默认隐藏该元素:&lt;element id="anchor" style="display: none" /&gt;。 如果页面上没有id=hash的可见元素,浏览器不会跳转。

    创建一个脚本,检查 url 中的哈希,然后找到并显示 prrpopriate 元素(默认隐藏)。

    通过将 onclick 事件绑定到链接并指定 return false; 作为 onclick 事件的结果来禁用默认的“类似哈希的链接”行为。

当我实现标签时,我写了类似的东西:

    <script>
    $(function ()          
        if (location.hash != "") 
            selectPersonalTab(location.hash);
        
        else 
            selectPersonalTab("#cards");
        
    );

    function selectPersonalTab(hash) 
        $("#personal li").removeClass("active");
        $("a[href$=" + hash + "]").closest("li").addClass("active");
        $("#personaldata > div").hide();
        location.hash = hash;
        $(hash).show();
    

    $("#personal li a").click(function (e) 
        var t = e.target;
        if (t.href.indexOf("#") != -1) 
            var hash = t.href.substr(t.href.indexOf("#"));
            selectPersonalTab(hash);
            return false;
        
    );
</script>

【讨论】:

【参考方案6】:

没有一个答案对我来说不够好,我看到页面跳转到锚点,然后跳转到顶部以获得一些解决方案,有些答案根本不起作用,可能是多年来的变化。希望我的功能对某人有所帮助。

/**
 * Prevent automatic scrolling of page to anchor by browser after loading of page.
 * Do not call this function in $(...) or $(window).on('load', ...),
 * it should be called earlier, as soon as possible.
 */
function preventAnchorScroll() 
    var scrollToTop = function () 
        $(window).scrollTop(0);
    ;
    if (window.location.hash) 
        // handler is executed at most once
        $(window).one('scroll', scrollToTop);
    

    // make sure to release scroll 1 second after document readiness
    // to avoid negative UX
    $(function () 
        setTimeout(
            function () 
                $(window).off('scroll', scrollToTop);
            ,
            1000
        );
    );

【讨论】:

迄今为止我找到的最佳解决方案。并且实际上看到了很多。 谢谢你!经过数小时的尝试,也是唯一对我有用的解决方案,但对我来说,这个解决方案最好的部分是我不必删除哈希。 如果滚动条在页面加载时已经位于页面顶部,则此方法不起作用,然后它将像往常一样向下滚动,页面完成后跳转到顶部。有谁知道是这种情况吗? @robgha01 请确保该函数尽快执行并且不等待任何事件,这是错误的:$(document).ready(function () preventAnchorScroll(); );,只需在 JavaScript 最开头调用该函数即可。我现在对其进行了测试,适用于 Chrome、Firefox 和 Opera。【参考方案7】:

脏 CSS 只修复每次使用锚点时保持向上滚动(如果您仍想使用锚点进行滚动跳转,则无用,对于深度链接非常有用):

.elementsWithAnchorIds::before 
   content: "";
   display: block;
   height: 9999px;
   margin-top: -9999px; //higher thin page height

【讨论】:

太聪明了! 我喜欢这个【参考方案8】:

虽然接受的答案确实有效,但我确实发现有时,尤其是在包含滚动条会疯狂跳动的大图像的页面上

 window.scrollTo(0, 0);

这可能会分散用户的注意力。

我最终确定的解决方案其实很简单,就是在目标上使用与location.hash不同的ID

例如:

这是其他页面上的链接

<a href="/page/with/tabs#tab2">Some info found in tab2 on tabs page</a>

当然,如果标签页上有 ID 为 tab2 的元素,加载时窗口会跳转到它。

所以你可以在 ID 上附加一些东西来防止它:

<div id="tab2-noScroll">tab2 content</div>

然后您可以在 javascript 中将 "-noScroll" 附加到 location.hash

<script type="text/javascript">
    $(function() 

        var tabContent = $(".tab_content");
        var tabs = $("#menu li");
        var hash = window.location.hash;


     tabContent.not(hash + '-noScroll').hide();                           
        if(hash=="")        //^ here
      $('#tab1-noScroll').fadeIn();
     
        tabs.find('[href=' + hash + ']').parent().addClass('active');

        tabs.click(function() 
            $(this).addClass('active').siblings().removeClass('active');
            tabContent.hide();
            var activeTab = $(this).find("a").attr("href") + '-noScroll'; 
                                                               //^ and here

            $(activeTab).fadeIn();
           return false;
        );

    );
</script>

【讨论】:

【参考方案9】:

在我的例子中,因为 CSS 弹出窗口使用了锚链接,所以我使用了这种方式:

点击时首先保存 pageYOffset,然后将 ScrollTop 设置为:

$(document).on('click','yourtarget',function()
        var st=window.pageYOffset;
        $('html, body').animate(
                'scrollTop' : st
            );
);

【讨论】:

在尝试了其他解决方案之后,这是对我有用的解决方案,在我的情况下,我正在使用的网站使用 url 中的 # 来加载结帐的特定部分。我没有修改 url 中哈希的结帐功能,而是使用了这个。谢谢【参考方案10】:

我想我已经找到了一种无需重做功能即可使用 UI 选项卡的方法。到目前为止,我还没有发现任何问题。

    $( ".tabs" ).tabs();
    $( ".tabs" ).not(".noHash").bind("tabsshow", function(event, ui)  
        window.location.hash = "tab_"+ui.tab.hash.replace(/#/,"");
        return false;
    );

    var selectedTabHash = window.location.hash.replace(/tab_/,"");
    var index = $( ".tabs li a" ).index($(".tabs li a[href='"+selectedTabHash+"']"));
    $( ".tabs" ).not(".noHash").tabs('select', index);

全部在一个就绪事件中。它为散列添加“tab_”,但在单击和加载散列的页面时都可以使用。

【讨论】:

【参考方案11】:

这将适用于 bootstrap v3

$(document).ready(function() 
  if ($('.nav-tabs').length) 
    var hash = window.location.hash;
    var hashEl = $('ul.nav a[href="' + hash + '"]');
    hash && hashEl.tab('show');

    $('.nav-tabs a').click(function(e) 
      e.preventDefault();
      $(this).tab('show');
      window.location.hash = this.hash;
    );

    // Change tab on hashchange
    window.addEventListener('hashchange', function() 
      var changedHash = window.location.hash;
      changedHash && $('ul.nav a[href="' + changedHash + '"]').tab('show');
    , false);
  
);
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.0/css/bootstrap.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.0/js/bootstrap.min.js"></script>
<div class="container">
<ul class="nav nav-tabs">
  <li class="active"><a data-toggle="tab" href="#home">Home</a></li>
  <li><a data-toggle="tab" href="#menu1">Menu 1</a></li>
</ul>

<div class="tab-content">
  <div id="home" class="tab-pane fade in active">
    <h3>HOME</h3>
    <p>Some content.</p>
  </div>
  <div id="menu1" class="tab-pane fade">
    <h3>Menu 1</h3>
    <p>Some content in menu 1.</p>
  </div>
</div>
</div>

【讨论】:

【参考方案12】:

另一种方法

尝试检查页面是否已滚动,然后才重置位置:

var scrolled = false;

$(window).scroll(function()
  scrolled = true;
);

if ( window.location.hash && scrolled ) 
  $(window).scrollTop( 0 );

Heres a demo

【讨论】:

不工作兄弟...初始负载在底部...刷新后它保持在顶部【参考方案13】:

我在 Firefox 中使用上述 setTimeout 方法并没有取得多大成功。

我使用了 onload 函数,而不是 setTimeout:

window.onload = function () 
    if (location.hash) 
        window.scrollTo(0, 0);
    
;

不幸的是,它仍然非常有问题。

【讨论】:

因为 onload 是在所有内容(包括照片)都完全加载后运行的......所以这样当然会出现故障【参考方案14】:

我在这些解决方案上没有取得任何一致的成功。

显然是因为跳转发生在 Javascript 之前 => 参考(http://forum.jquery.com/topic/preventing-anchor-jump)

我的解决方案是默认使用 CSS 将所有锚点放在顶部。

.scroll-targetposition:fixed;top:0;left:0;

然后使用jquery滚动到目标锚的父级,或者兄弟级(可能是一个空的em标签)

<a class="scroll-target" name="section3"></a><em>&nbsp</em>

使用哈希输入 URL 时滚动的 jquery 示例 (页面不得已加载到窗口/选项卡中,这包括来自其他/外部来源的链接)

setTimeout(function() 
    if (window.location.hash)                
        var hash = window.location.hash.substr(1);   
        var scrollPos = $('.scroll-target[name="'+hash+'"]').siblings('em').offset().top; 
        $("html, body").animate( scrollTop: scrollPos , 1000);    
    
, 1);

您还需要在页面上防止默认锚点点击,然后滚动到它们的目标

<a class="scroll-to" href="#section3">section three</a>

和jquery

$('a.scroll-to').click(function()
    var target = $(this).attr('href').substr(1);
    var scrollPos = $('.scroll-target[name="'+target+'"]').siblings('em').offset().top; 
    $("html, body").animate( scrollTop: scrollPos , 1000);
    return false;
);

这种方法的好处是锚标记目标,在结构上保持在相关内容旁边,尽管它们的 CSS 位置在顶部。 这应该意味着搜索引擎爬虫不会有问题。 干杯,我希望这会有所帮助格雷

【讨论】:

【参考方案15】:

尝试这样做以防止客户端对 hashchanged(在您的事件处理程序内部)进行任何类型的垂直滚动:

var sct = document.body.scrollTop;
document.location.hash = '#next'; // or other manipulation
document.body.scrollTop = sct;

(浏览器重绘)

【讨论】:

【参考方案16】:

通过这样做解决了我的问题:

// navbar height 
var navHeigth = $('nav.navbar').height();    

// Scroll to anchor function
var scrollToAnchor = function(hash) 
  // If got a hash
  if (hash) 
    // Scroll to the top (prevention for Chrome)
    window.scrollTo(0, 0);
    // Anchor element
    var term = $(hash);

    // If element with hash id is defined
    if (term) 

      // Get top offset, including header height
      var scrollto = term.offset().top - navHeigth;

      // Capture id value
      var id = term.attr('id');
      // Capture name value
      var name = term.attr('name');

      // Remove attributes for FF scroll prevention
      term.removeAttr('id').removeAttr('name');
      // Scroll to element
      $('html, body').animate(scrollTop:scrollto, 0);

      // Returning id and name after .5sec for the next scroll
      setTimeout(function() 
        term.attr('id', id).attr('name', name);
      , 500);
    
  
;

// if we are opening the page by url
if (location.hash) 
  scrollToAnchor(location.hash);


// preventing default click on links with an anchor
$('a[href*="#"]').click(function(e) 
  e.preventDefault();
  // hash value
  var hash = this.href.substr(this.href.indexOf("#"));
  scrollToAnchor(hash);
);`

【讨论】:

以上是关于加载页面时如何禁用锚点“跳转”?的主要内容,如果未能解决你的问题,请参考以下文章

单击锚点后如何刷新页面并加载到顶部,忽略锚点并重置回顶部?

链接到锚点并强制重新加载当前页面

单击链接时禁用默认锚点跳转

如何在鼠标悬停时播放引导 4 轮播,并在页面加载时禁用自动播放?

如何仅在页面加载时禁用 DataTables 中的排序?

当数据在javascript codeigniter php中使用ajax成功功能时,如何禁用页面重新加载?