160

コンテンツをロードするために ajax を使用しているページがいくつかあり、ページへのディープ リンクが必要な場合がいくつかあります。「ユーザー」へのリンクを用意して「設定」をクリックするように指示する代わりに、ユーザーをuser.aspx#settingsにリンクできると便利です。

人々がセクションへの正しいリンク (技術サポートなど) を提供できるようにするために、ボタンがクリックされるたびに URL のハッシュを自動的に変更するように設定しました。もちろん、唯一の問題は、これが発生すると、ページがこの要素までスクロールされることです。

これを無効にする方法はありますか?以下は、私がこれまでにこれをどのように行っているかです。

$(function(){
    //This emulates a click on the correct button on page load
    if(document.location.hash){
     $("#buttons li a").removeClass('selected');
     s=$(document.location.hash).addClass('selected').attr("href").replace("javascript:","");
     eval(s);
    }

    //Click a button to change the hash
    $("#buttons li a").click(function(){
            $("#buttons li a").removeClass('selected');
            $(this).addClass('selected');
            document.location.hash=$(this).attr("id")
            //return false;
    });
});

ページのスクロールが停止することを望んでいましたreturn false;が、リンクがまったく機能しなくなります。ナビゲートできるように、今のところコメントアウトされています。

何か案は?

4

17 に答える 17

111

history.replaceStateまたはhistory.pushState* を使用してハッシュを変更します。これは、関連する要素へのジャンプをトリガーしません。

$(document).on('click', 'a[href^=#]', function(event) {
  event.preventDefault();
  history.pushState({}, '', this.href);
});

JSFiddle のデモ

*履歴の前後のサポートが必要な場合

履歴動作

を使用history.pushStateしていて、ユーザーがブラウザの履歴ボタン (進む/戻る) を使用したときにページをスクロールしたくない場合は、実験的なscrollRestoration設定(Chrome 46+ のみ)を確認してください。

history.scrollRestoration = 'manual';

ブラウザのサポート

于 2013-01-28T11:09:53.997 に答える
111

ステップ 1: ハッシュが設定されるまで、ノード ID を解除する必要があります。これは、ハッシュが設定されている間にノードから ID を削除し、それを再度追加することによって行われます。

hash = hash.replace( /^#/, '' );
var node = $( '#' + hash );
if ( node.length ) {
  node.attr( 'id', '' );
}
document.location.hash = hash;
if ( node.length ) {
  node.attr( 'id', hash );
}

ステップ 2: 一部のブラウザーは、ID が付けられたノードが最後に表示された場所に基づいてスクロールをトリガーするため、少し手助けする必要があります。ビューポートの上部にエクストラを追加divし、その ID をハッシュに設定してから、すべてをロールバックする必要があります。

hash = hash.replace( /^#/, '' );
var fx, node = $( '#' + hash );
if ( node.length ) {
  node.attr( 'id', '' );
  fx = $( '<div></div>' )
          .css({
              position:'absolute',
              visibility:'hidden',
              top: $(document).scrollTop() + 'px'
          })
          .attr( 'id', hash )
          .appendTo( document.body );
}
document.location.hash = hash;
if ( node.length ) {
  fx.remove();
  node.attr( 'id', hash );
}

ステップ 3: プラグインでラップし、location.hash...に書き込む代わりにそれを使用します。

于 2009-09-28T23:06:50.333 に答える
91

かなり簡単な解決策を見つけたかもしれないと思います。問題は、URL のハッシュが、スクロール先のページの要素でもあることです。ハッシュの先頭にテキストを追加すると、既存の要素を参照しなくなります!

$(function(){
    //This emulates a click on the correct button on page load
    if(document.location.hash){
     $("#buttons li a").removeClass('selected');
     s=$(document.location.hash.replace("btn_","")).addClass('selected').attr("href").replace("javascript:","");
     eval(s);
    }

    //Click a button to change the hash
    $("#buttons li a").click(function(){
            $("#buttons li a").removeClass('selected');
            $(this).addClass('selected');
            document.location.hash="btn_"+$(this).attr("id")
            //return false;
    });
});

page.aspx#btn_elementIDこれで、ページ上の実際の ID ではないURL が表示されます。「btn_」を削除して、実際の要素 ID を取得するだけです

于 2009-10-02T20:01:45.283 に答える
4

私は最近、状態を維持するために依存するカルーセルを構築していましたが、イベントが発生しwindow.location.hashたときに、Chrome および webkit ブラウザーが (目に見えないターゲットに対しても) ぎこちなくスクロールを強制することを発見しました。window.onhashchange

伝播を停止するハンドラを登録しようとしても:

$(window).on("hashchange", function(e) { 
  e.stopPropogation(); 
  e.preventDefault(); 
});

デフォルトのブラウザの動作を止めるために何もしませんでした。私が見つけた解決策はwindow.history.pushState、望ましくない副作用を引き起こすことなくハッシュを変更することでした。

 $("#buttons li a").click(function(){
    var $self, id, oldUrl;

    $self = $(this);
    id = $self.attr('id');

    $self.siblings().removeClass('selected'); // Don't re-query the DOM!
    $self.addClass('selected');

    if (window.history.pushState) {
      oldUrl = window.location.toString(); 
      // Update the address bar 
      window.history.pushState({}, '', '#' + id);
      // Trigger a custom event which mimics hashchange
      $(window).trigger('my.hashchange', [window.location.toString(), oldUrl]);
    } else {
      // Fallback for the poors browsers which do not have pushState
      window.location.hash = id;
    }

    // prevents the default action of clicking on a link.
    return false;
});

その後、通常の hashchange イベントとmy.hashchange次の両方をリッスンできます。

$(window).on('hashchange my.hashchange', function(e, newUrl, oldUrl){
  // @todo - do something awesome!
});
于 2015-03-25T13:02:24.120 に答える
3

元のコードのスニペット:

$("#buttons li a").click(function(){
    $("#buttons li a").removeClass('selected');
    $(this).addClass('selected');
    document.location.hash=$(this).attr("id")
});

これを次のように変更します。

$("#buttons li a").click(function(e){
    // need to pass in "e", which is the actual click event
    e.preventDefault();
    // the preventDefault() function ... prevents the default action.
    $("#buttons li a").removeClass('selected');
    $(this).addClass('selected');
    document.location.hash=$(this).attr("id")
});
于 2010-07-22T18:37:02.167 に答える
2

ええと、私はやや大雑把ですが、確実に機能する方法を持っています。
現在のスクロール位置を一時変数に保存し、ハッシュを変更した後にリセットするだけです。:)

したがって、元の例では次のようになります。

$("#buttons li a").click(function(){
        $("#buttons li a").removeClass('selected');
        $(this).addClass('selected');

        var scrollPos = $(document).scrollTop();
        document.location.hash=$(this).attr("id")
        $(document).scrollTop(scrollPos);
});
于 2014-08-24T17:45:29.110 に答える
2

より関連性の高い質問はすべて、ここを指している重複としてマークされているため、ここに追加します…</p>

私の状況はより単純です:

  • a[href='#something']ユーザーがリンク ( )をクリックする
  • クリック ハンドラーは次のことを行います。e.preventDefault()
  • スムーズスクロール機能:$("html,body").stop(true,true).animate({ "scrollTop": linkoffset.top }, scrollspeed, "swing" );
  • それから window.location = link;

このように、スクロールが発生し、場所が更新されてもジャンプしません。

于 2014-07-18T08:38:22.223 に答える
1

これは不可能だと思います。私の知る限り、ブラウザが変更された場所までスクロールしないdocument.location.hashのは、ページ内にハッシュが存在しない場合のみです。

この記事はあなたの質問とは直接関係ありませんが、変更時の典型的なブラウザの動作について説明していますdocument.location.hash

于 2009-09-28T22:12:48.523 に答える
0

履歴対応タブの私のソリューションは次のとおりです。

    var tabContainer = $(".tabs"),
        tabsContent = tabContainer.find(".tabsection").hide(),
        tabNav = $(".tab-nav"), tabs = tabNav.find("a").on("click", function (e) {
                e.preventDefault();
                var href = this.href.split("#")[1]; //mydiv
                var target = "#" + href; //#myDiv
                tabs.each(function() {
                    $(this)[0].className = ""; //reset class names
                });
                tabsContent.hide();
                $(this).addClass("active");
                var $target = $(target).show();
                if ($target.length === 0) {
                    console.log("Could not find associated tab content for " + target);
                } 
                $target.removeAttr("id");
                // TODO: You could add smooth scroll to element
                document.location.hash = target;
                $target.attr("id", href);
                return false;
            });

最後に選択したタブを表示するには:

var currentHashURL = document.location.hash;
        if (currentHashURL != "") { //a tab was set in hash earlier
            // show selected
            $(currentHashURL).show();
        }
        else { //default to show first tab
            tabsContent.first().show();
        }
        // Now set the tab to active
        tabs.filter("[href*='" + currentHashURL + "']").addClass("active");

通話中に注意し*=てください。filterこれは jQuery 固有のものであり、これがないと、履歴対応のタブは失敗します。

于 2014-03-08T20:51:01.603 に答える
0

これを行うもう 1 つの方法は、ビューポートの上部に非表示の div を追加することです。この div には、ハッシュが URL に追加される前にハッシュの ID が割り当てられます。そのため、スクロールは行われません。

于 2011-02-03T12:18:46.083 に答える
0

このソリューションは、実際の scrollTop に div を作成し、ハッシュを変更した後に削除します。

$('#menu a').on('click',function(){
    //your anchor event here
    var href = $(this).attr('href');
    window.location.hash = href;
    if(window.location.hash == href)return false;           
    var $jumpTo = $('body').find(href);
    $('body').append(
        $('<div>')
            .attr('id',$jumpTo.attr('id'))
            .addClass('fakeDivForHash')
            .data('realElementForHash',$jumpTo.removeAttr('id'))
            .css({'position':'absolute','top':$(window).scrollTop()})
    );
    window.location.hash = href;    
});
$(window).on('hashchange', function(){
    var $fakeDiv = $('.fakeDivForHash');
    if(!$fakeDiv.length)return true;
    $fakeDiv.data('realElementForHash').attr('id',$fakeDiv.attr('id'));
    $fakeDiv.remove();
});

ページの読み込み時にアンカー イベントをトリガーするオプション:

$('#menu a[href='+window.location.hash+']').click();
于 2014-03-27T13:21:01.587 に答える
0

hashchange の前にスクロールをその位置にリセットする必要があると思います。

$(function(){
    //This emulates a click on the correct button on page load
    if(document.location.hash) {
        $("#buttons li a").removeClass('selected');
        s=$(document.location.hash).addClass('selected').attr("href").replace("javascript:","");
        eval(s);
    }

    //Click a button to change the hash
    $("#buttons li a").click(function() {
            var scrollLocation = $(window).scrollTop();
            $("#buttons li a").removeClass('selected');
            $(this).addClass('selected');
            document.location.hash = $(this).attr("id");
            $(window).scrollTop( scrollLocation );
    });
});
于 2017-04-16T12:20:33.310 に答える
0

ページで id を一種のアンカー ポイントとして使用し、ユーザーに #something を URL の最後に追加させ、独自に定義したアニメーションを使用してページをその #something セクションにスクロールさせるシナリオがある場合javascript 関数、hashchange イベント リスナーはそれを行うことができません。

たとえば、hashchange イベントの直後にデバッガーを配置するだけの場合 (まあ、私は jquery を使用しますが、要点はわかります):

$(window).on('hashchange', function(){debugger});

URLを変更してEnterボタンを押すとすぐに、ページが対応するセクションですぐに停止することに気付くでしょう。その後、独自に定義したスクロール機能がトリガーされ、そのセクションまでスクロールします。ひどい。

私の提案は次のとおりです。

  1. スクロール先のセクションへのアンカーポイントとして id を使用しないでください。

  2. 私のようにIDを使用する必要がある場合。代わりに 'popstate' イベント リスナーを使用してください。URL に追加したセクションまで自動的にスクロールすることはありません。代わりに、popstate イベント内で独自に定義した関数を呼び出すことができます。

    $(window).on('popstate', function(){myscrollfunction()});

最後に、独自に定義したスクロール関数でちょっとしたトリックを行う必要があります。

    let hash = window.location.hash.replace(/^#/, '');
    let node = $('#' + hash);
    if (node.length) {
        node.attr('id', '');
    }
    if (node.length) {
        node.attr('id', hash);
    }

タグのIDを削除してリセットしてください。

これでうまくいくはずです。

于 2018-05-04T21:38:24.097 に答える
-5

ドキュメントの準備ができたら、このコードを jQuery に追加するだけです

参照: http://css-tricks.com/snippets/jquery/smooth-scrolling/

$(function() {
  $('a[href*=#]:not([href=#])').click(function() {
    if (location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'') && location.hostname == this.hostname) {
      var target = $(this.hash);
      target = target.length ? target : $('[name=' + this.hash.slice(1) +']');
      if (target.length) {
        $('html,body').animate({
          scrollTop: target.offset().top
        }, 1000);
        return false;
      }
    }
  });
});
于 2014-11-25T14:43:08.933 に答える