web-dev-qa-db-ja.com

pushState()およびpopState():ブラウザの履歴を操作する

私はAjaxスタイルのWebサイトを作成したい小さなプロジェクトに取り組んでいます。コンテンツはjQueryのload()で読み込まれます。ご存知のように、これの欠点は、表示されるコンテンツに応じてURLが変更されないことです。これを機能させるには、pushState()を使用できます。これはクロスブラウザでサポートされていないため、プラグイン_history.js_を使用しました。

これは非常にうまく機能していますが、問題は、戻るボタンと進むボタンが正常に機能しておらず、何が間違っているのかわからないことです。 URLは正しく変更されており、コンテンツも変更されていますが、タイトルはまったく変更されていません。タイトルとは、ブラウザウィンドウのウィンドウ(またはタブ)のタイトルとして表示されるものを意味します。つまりロードされたページの_<title>_ ORそのページを参照するリンクのタイトル属性(同じです)。これは、次の事実と関係があると思います。タイトルが必要なページのセクションのみを呼び出します(つまり、load()に_#content_を追加します)。それでもそのページのタイトルが必要です。これが私のテストケースです。 (2013年12月28日以降は利用できなくなりました。)jQueryファイル:

_$(document).ready(function () {
    var firstLink = $("ul > li:first-child > a");
    var menuLink = $("ul > li > a");
    var firstLoadedHtml = firstLink.attr("href") + " #content";

    $("#sectionContainer").hide().load(firstLoadedHtml).fadeIn("fast");
    firstLink.addClass("active");   

    menuLink.click(function(e) {
        history.pushState(null, null, this.href);

        e.preventDefault();
        e.stopImmediatePropagation();

        var CurLink = $(this);
        var newLoadedHtml = CurLink.attr("href") + " #content";
        var oldSection = $(".contentPage");

        $("#sectionContainer").hide().load(newLoadedHtml).fadeIn("fast");
        menuLink.removeClass("active");
        CurLink.addClass("active");
    });

    $(window).bind('popstate', function() {
            var returnLocation = history.location || document.location;

            $('#sectionContainer').load(returnLocation + "#content");
    });
});
_

また、基本ページ(/ sectionLoaderTest /など)に戻ると、最初のページのコンテンツが読み込まれるまでしばらくの間空白になることにも注意しました。これを最適化する方法はありますか?

さらに、jQueryを使用して、クリックされたリンクにアクティブクラスを追加しています。これが履歴に応じて変化することをどのように確認できますか?ユーザーが戻ったときに正しいリンクが強調表示されるようにするには?

したがって、3つの質問は次のとおりです。

  1. 前後に移動するときにタイトルを機能させる
  2. メインページの読み込み時間を最適化する
  3. 前後に移動するときにアクティブクラスを修正する

すべての助けを歓迎します!

注1:history.jsと独自のスクリプトを基に構築したいので、_< HTML5_ブラウザーのサポートを維持します。私はこれを好む。1。これはうまくいく必要があることを知っている、何かがうまくいかないだけだ。 2.まったく新しいスクリプトを理解するのではなく、自分の解決策を見つけて、すでに作成したスクリプトに実装できれば、時間を節約できます。

注2:賞金は私の質問(3)のすべてに答えることができる彼または彼女にのみ与えられます!

6
Bram Vanroy

回答1-前後に移動するときにタイトルが機能するようにします

私が理解した限りでは、リンクからドキュメントタイトルhtmlを変更したいのですが、divにロードされています。 jQuery _.load_を介してdivにファイルをロードする場合、ajaxリクエストの後に完全な応答テキストを挿入するだけです。したがって、titleまたはmetaタグのようなdivに含めるべきではないすべてのものを使用します。ただし、現在のドキュメントのタイトル(_http://bramvanroy.be/sectionLoaderTest/index.html_)は、div内のtitleタグではなく、headタグ内にあるtitleで定義されています。そのため、ドキュメントのタイトルは変更されません。

では、どうすれば修正できますか?

良い質問です。title要素内のdiv要素は無効であるため、ほとんどのブラウザはそれを削除するため、これを使用することはできません。

_document.title = $("#sectionContainer title").text();
_

title要素が存在しない可能性があるためです。

したがって、必要なのはjQuery _.load_関数からの直接応答です。関数にコールバック引数を追加することで取得できます。

_$("#sectionContainer")
    .hide()
    .load(newLoadedHtml, function(responseText) {
        document.title = $(responseText).filter("title").text();
    })
    .fadeIn("fast");
_

理解できないかもしれませんが、私が_.filter_関数ではなく_.find_を使用している理由です。これは、jQueryがhtmlからhtmlhead、およびbodyタグを解析しているが、子要素を削除していないためです。

回答2-メインページの読み込み時間を最適化します

ドキュメントは上から下にロードされています。

したがって、最初にcss、JavaScriptなどをロードしてから、メインドキュメントをロードする必要があります。 jQueryは実行前に常にドキュメントを待機しているため、すべてのscript要素を本文の最後の直前に配置して、HTMLを前にロードできるようにすることはそれほど悪い考えではありません。

ところで、私は最初にこの問題を抱えていましたが、その後すべてがキャッシュされ、ドキュメントが非常に高速に読み込まれていました。

回答3-前後に移動するときのアクティブクラスを修正します

href要素のa属性をループして、History.getState()のデータと比較します。簡単なはずです。

コードにいくつかの間違いをしました-修正されたコード:

ハッシュ_#content_をすべてのURLに追加しました。意味がなく、jQueryによって再び削除されます: https://github.com/jquery/jquery/blob/master/src /ajax.js#L617 (行から来る:158、190、337、617-ラッシュは行6にあります)

_$(document).ready(function () {
    var firstLink = $("ul > li:first-child > a");
    var menuLink = $("ul > li > a");
    var firstLoadedHtml = firstLink.attr("href");

    $("#sectionContainer").hide().load(firstLoadedHtml).fadeIn("fast");
    firstLink.addClass("active");   

    menuLink.click(function(e) {

        e.preventDefault();
        e.stopImmediatePropagation();

        var newLoadedHtml = $(this).attr("href");

        History.pushState(null, newLoadedHtml, newLoadedHtml);

        $("#sectionContainer")
            .hide()
            .load(newLoadedHtml, function(responseText) {
                document.title = $(responseText).filter("title").text();
            })
            .fadeIn("fast");
    });

    History.Adapter.bind(window, "statechange", function() {
        menuLink.removeClass("active");
        $("a[href='" + History.getState().title + "']").addClass("active");
        $('#sectionContainer').load(document.location.href, function(responseText) {
            document.title = $(responseText).filter("title").text();
        }); 
    });
});
_
11
noob

davis.jsjQuery Pusherなどの利用可能なルーティングプラグインを試すこともできます https://github.com/salvan13/jquery-pusher

0
Deepak Thomas