ページをリロードせずにクエリ文字列を変更する


114

フォトギャラリーを作成しています。写真を閲覧するときにクエリ文字列とタイトルを変更できるようにしたいと考えています。

私が探している動作は、連続/無限ページの一部の実装でよく見られます。クエリ文字列を下にスクロールしても、ページ番号(http://x.com?page=4)が増加し続けます。これは理論的には単純ですが、主要なブラウザで安全なものを求めています。

私はこの素晴らしい投稿を見つけ、で例を追おうとしましたwindow.history.pushstateが、それは私にはうまくいかないようです。また、ブラウザーの履歴を変更する必要がないので、それが理想的かどうかはわかりません。

写真が変更されるたびにページをリロードすることなく、現在表示されている写真をブックマークする機能を提供できるようにしたいだけです。

以下は、クエリ文字列を変更する無限ページの例です。http//tumbledry.org/

UPDATEはこのメソッドを見つけました:

window.location.href = window.location.href + '#abc';

それは私のために動作するように見えますが、私は新しいクロムを使用しています。それはおそらく古いブラウザでいくつかの問題を引き起こすでしょうか?


クエリ文字列を動的に更新するいくつかのサンプルサイトへのリンクを投稿できますか?私はそれができるとは思わないが、あなたはハッシュ値を変更することができ、それはあなた望むものを得るのに十分かもしれない。
ポインティ




@クエンティン。投票できるのは1つだけです...:)
gdoronは

回答:


185

ハッシュの変更を探している場合、ソリューションは正常に動作します。ただし、クエリを変更する場合は、前述のようにpushStateを使用できます。これは、適切に実装するのに役立つ例です。私はテストし、それはうまくいきました:

if (history.pushState) {
    var newurl = window.location.protocol + "//" + window.location.host + window.location.pathname + '?myNewUrlQuery=1';
    window.history.pushState({path:newurl},'',newurl);
}

ページは再読み込みされませんが、URLクエリの変更のみが可能です。プロトコルまたはホストの値を変更することはできません。そしてもちろん、HTML5 History APIを処理できる最新のブラウザーが必要です。

詳細については:

http://diveintohtml5.info/history.html

https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Manipulating_the_browser_history


6
私はあなたがwindow.location.protocol + '//' + window.location.hostちょうどに短縮できると信じています: window.location.origin
Garrett

4
また、情報を少し追加するために、相対パスはでも機能しhistory.pushState()ます。実state引数も不要です。これらはどちらもhistory.pushState(null, '', '/foo?bar=true')、新しいURLが同じホスト/ポートにある場合のように、簡単なことを実行できることを意味します。
Blaskovicz

23
新しい状態をブラウザの履歴に表示したくない場合history.replaceState()は、同じ引数を使用できます。
Blackus

6
それ以外の場合は、ブラウザで[戻る]ボタンを2回クリックする必要があります
Zhenya

4
最近のブラウザであなただけ行うことができます:if (window.history.pushState) { const newURL = new URL(window.location.href); newURL.search = '?myNewUrlQuery=1'; window.history.pushState({ path: newURL.href }, '', newURL.href); }
アラン・バプティスタ

8

ファビオの答えに基づいて、私はこの質問に出くわした人におそらく役立つ2つの関数を作成しました。これら2つの関数を使用するinsertParam()と、キーと値を引数として呼び出すことができます。URLパラメータを追加するか、同じパラメータのクエリパラメータがすでに存在する場合は、そのパラメータを新しい値に変更します。

//function to remove query params from a URL
function removeURLParameter(url, parameter) {
    //better to use l.search if you have a location/link object
    var urlparts= url.split('?');   
    if (urlparts.length>=2) {

        var prefix= encodeURIComponent(parameter)+'=';
        var pars= urlparts[1].split(/[&;]/g);

        //reverse iteration as may be destructive
        for (var i= pars.length; i-- > 0;) {    
            //idiom for string.startsWith
            if (pars[i].lastIndexOf(prefix, 0) !== -1) {  
                pars.splice(i, 1);
            }
        }

        url= urlparts[0] + (pars.length > 0 ? '?' + pars.join('&') : "");
        return url;
    } else {
        return url;
    }
}

//function to add/update query params
function insertParam(key, value) {
    if (history.pushState) {
        // var newurl = window.location.protocol + "//" + window.location.host + search.pathname + '?myNewUrlQuery=1';
        var currentUrlWithOutHash = window.location.origin + window.location.pathname + window.location.search;
        var hash = window.location.hash
        //remove any param for the same key
        var currentUrlWithOutHash = removeURLParameter(currentUrlWithOutHash, key);

        //figure out if we need to add the param with a ? or a &
        var queryStart;
        if(currentUrlWithOutHash.indexOf('?') !== -1){
            queryStart = '&';
        } else {
            queryStart = '?';
        }

        var newurl = currentUrlWithOutHash + queryStart + key + '=' + value + hash
        window.history.pushState({path:newurl},'',newurl);
    }
}

あなたの関数はnew URLSearchParams()、ネイティブメソッドを設定および削除するよりも優れていますか?どちらの場合でも、それを歴史にhistory.pushState()
反映さ

1
new URLSearchParams()IEのどのバージョンでもサポートされていません
jmona789

ありがとう@ jmona789これは私にとって完璧に機能し、まさに私が探していたものでした
mknopf

7

私は次のJavaScriptライブラリを使用して大きな成功を収めました。

https://github.com/balupton/jquery-history

HTML5履歴APIと、古いブラウザーのフォールバックメソッド(#を使用)をサポートしています。

このライブラリは本質的に `history.pushState 'の周りのポリフィルです。


驚くばかり!すべてのブラウザでテストしましたか?
ソニックソウル

私の実装は、IE7以降、Firefox 3.6以降、Safari 5およびChrome 16以降でテストされました。それはおそらく他のブラウザでも動作しますが、それを使用して展開されたいくつかのシステムには不満はありません。
Ian Newson

すごい。そう今.. window.location.hrefに書き込むときに&の代わりに単に#を置くだけでうまくいきます。ページをリロードしません。IEでテストしたら壊れると思います。その時点で、提案したライブラリを使用します。感謝
ソニックソウル

#メソッドは、非常に幅広いブラウザーをサポートしている点で優れています。URLの#部分はブラウザから送信されないため、サーバーへのリクエストにその情報を含める必要がある場合、状況は複雑になる可能性があります。私が参照したライブラリを含め、その方法はいくつかあります。さらに、HTML5履歴APIを使用すると、URLを全体的に短くすることができ、状態を復元するために必要なクライアント側の作業が少なくなります。
Ian Newson

#メソッドは、ソーシャルメディアの共有にも問題があります。共有に戻るプレビューまたはリンクを作成するとき、Twitter、Facebook、およびおそらく他の人はアンカータグでうまく機能しません。
mirth23

5

Fabioの回答を改善し、ページをリロードせずにURL文字列にカスタムキーを追加する関数を作成したいと考えています。

function insertUrlParam(key, value) {
    if (history.pushState) {
        let searchParams = new URLSearchParams(window.location.search);
        searchParams.set(key, value);
        let newurl = window.location.protocol + "//" + window.location.host + window.location.pathname + '?' + searchParams.toString();
        window.history.pushState({path: newurl}, '', newurl);
    }
}

0

次に、履歴APIはまさにあなたが探しているものです。レガシーブラウザもサポートする場合は、ブラウザが履歴APIを提供していない場合に、URLのハッシュタグの操作にフォールバックするライブラリを探します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.