JavaScriptを使用して新しいページを読み込まずに、ブラウザーでURLを変更する


297

現在のページにいくつかの影響を与える可能性があるが、ブラウザのURLも変更するJavaScriptアクションをどのように作成しますか?ユーザーがリロードまたはブックマークを押すと、新しいURLが使用されますか?

また、[戻る]ボタンで元のURLを再読み込みすることもできます。

JavaScriptの状態をURLに記録しようとしています。


1
これはいいですね。もちろん、同じドメインの変更に限定されます。しかし、パス(およびハッシュだけではない)のクライアント側の制御は、ページのリロードが多くのアプリにとって「最後の手段」の一種であるため、論理的なステップです。
harpo

1
「並べ替え」の良い使い方pushStatefor(i=1;i<50;i++){var txt="..................................................";txt=txt.slice(0,i)+"HTML5"+txt.slice(i,txt.length);history.pushState({}, "html5", txt);}
Derek款會功夫

この効果の実例:dujour.com
Ben

2
この効果の例:facebook.com(ライトボックスで画像を開くとき)

これは良い質問です。しかし、もしこの質問がこのようにして今日尋ねられたなら、「これは、あなたがあなたのためにすべてのコードを書いてもらうようなサイトではない」と反対票を投じられたという悲しい状況です。
dewd

回答:


118

HTML 5では、history.pushState関数を使用します。例として:

<script type="text/javascript">
var stateObj = { foo: "bar" };
function change_my_url()
{
   history.pushState(stateObj, "page 2", "bar.html");
}
var link = document.getElementById('click');
link.addEventListener('click', change_my_url, false);
</script>

そしてa href:

<a href="#" id='click'>Click to change url to bar.html</a>

戻るボタンリストにエントリを追加せずにURLを変更する場合は、history.replaceState代わりにを使用してください。


あなたが正しい、前回私がChromeで実験した。UbuntuでFirefox 3.6を試したところ、うまくいきませんでした。HTML5がFFで完全にサポートされるまで待つ必要があると思います
clu3

15
サンプルコードは、developer.mozilla.org /en/DOM/Manipulating_the_browser_historyからカットアンドペーストさます。この場合、fooとbarの意味を実際に説明するのは面倒です。
mikemaccana

2
fooとbarは何も意味しません。これは、後で取得できる任意に定義された状態オブジェクトです。
ポールディクソン

3
@Paul:うん、上の記事はその情報を提供しています。
mikemaccana

2
このコメントを投稿した時点で、Firefoxのchromeとsafariで動作します。ipadやiphoneのモバイルサファリでは運が悪い:(
Sid

187

あなたがサポートしていないブラウザで動作するようにそれをしたい場合history.pushStatehistory.popState、まだ、「古い」の方法は、ページのリロードが発生することはありませんフラグメント識別子を、設定することです。

基本的な考え方は、window.location.hash必要な状態情報をすべて含む値にプロパティを設定し、次にwindow.onhashchangeイベントを使用するか、サポートしていない古いブラウザーonhashchange(IE <8、Firefox <3.6)の場合、定期的に確認することですハッシュが変更されたかどうかを確認し(setIntervalたとえば、使用して)、ページを更新します。また、ページのロード時にハッシュ値を確認して、初期コンテンツを設定する必要があります。

jQueryを使用している場合は、ブラウザーがサポートする方法を使用するhashchangeプラグインがあります。他のライブラリ用のプラグインもあると思います。

注意が必要なことの1つは、ページ上のIDとの衝突です。これは、ブラウザーが一致するIDを持つ要素までスクロールするためです。


2
検索エンジンはこれらの内部リンク(ハッシュ)を無視しませんか?私のシナリオでは、クモにもこれらのリンクを拾ってもらいたいです。
Drew Noakes、

3
@Drew、私が知る限り、検索エンジンがページの一部を個別の結果として扱う方法はありません。
マシュークルムリー

8
検索エンジンはハッシュを見るようにする提案が用意されました:googlewebmastercentral.blogspot.com/2009/10/...
LKM

5
それをはるかに採用しているので、を使用しsetIntervalて検査する代わりにdocument.location.hashhashchangeイベントを使用できます。各ブラウザをサポートしているブラウザについては、こちらをご覧ください。私の現在のアプローチは、それをサポートするブラウザーでpush / popStateを使用することです。他のものではハッシュを設定し、hashchangeサポートしているブラウザでのみ監視します。これにより、IE <= 7には履歴のサポートがなくなりますが、有用なパーマリンクがあります。しかし、IE <= 7の歴史を誰が気にするのでしょうか?
Irae Carvalho

2
@gabeDelはい、Analyticsはハッシュを記録するとは思わないので、同じURLになります。より良い方法は_trackPageview、新しいページの「実際の」URL を手動で呼び出すことです。
Matthew Crumley、2012

37

window.location.hrefには、現在のURLが含まれています。そこから読み取ったり、追加したり、置き換えたりすることができます。これにより、ページがリロードされる場合があります。

どうやら、URLにJavaScriptの状態を記録してブックマークに追加したい場合は、ページをリロードせずに、現在のURLの#の後に追加し、onloadイベントによってJavaScriptの一部をトリガーして現在のURLを解析します。保存された状態が含まれているかどうかを確認するためのURL。

あなたが使用する場合?#の代わりに、ページを強制的にリロードしますが、ロード時に保存された状態を解析するため、これは実際には問題にならない可能性があります。これにより、進むボタンと戻るボタンも正しく機能します。


2
URLにJavaScriptの状態を記録することは、まさに私がやろうとしていることです
Steven Noble

21

これが可能だとしたら信じられないほどのセキュリティ問題になるので、これは不可能だと強く思います。たとえば、銀行のログインページのようなページを作成し、アドレスバーのURLを実際の銀行のように見せることができます。

おそらく、なぜこれをしたいのかを説明すれば、人々は別のアプローチを提案できるかもしれません...

[2011年に編集:2008年にこの回答を書いてから、同じ起源からのものである限りURLを変更できるHTML5テクニックに関して、より多くの情報が明らかになりました]


6
リロード以外の変更がパス、クエリ文字列、フラグメントに制限されていれば、それほど問題にはなりません。つまり、オーソリティ(ドメインなど)には制限されません。
Ollie Saunders

2
youtube.com/user/SilkyDKwan#p/u/2/gTfqaGYVfMgは可能な例です。ビデオを切り替えてみてください:)
Spidfire

受け入れられた回答でMatthew Chumleyが指摘しているように、location.hash(#の後のすべて)のみを変更できます。
ポールディクソン

2
あなたはフェイスブックを利用しますか?Facebook はを使用して、リロードせずにURL 変更しますhistory.pushState()
デレク━會功夫2012年

Paul Dixon、facebookの受信トレイに気づくはずです。左側の名前をクリックすると、URLが変更され、新しいチャットがチャットボックスに読み込まれ、ページが更新されません。また、WebGLには同じようなサイトがたくさんあります
Dheeraj Thedijje 14

8

ブラウザのセキュリティ設定により、表示されたURLを直接変更することはできません。あなたが引き起こすフィッシングの脆弱性を想像することができます。

ページを変更せずにURLを変更する信頼できる方法は、内部リンクまたはハッシュを使用することだけです。例えば:http://site.com/page.htmlはなりhttp://site.com/page.html#item1。この手法はhijax(AJAX +履歴の保存)でよく使用されます。

これを行うときは、hrefとしてハッシュを使用するアクションのリンクを使用することがよくあります。次に、要求されたハッシュを使用してアクションを決定および委任するjqueryでクリックイベントを追加します。

私はあなたが正しい道にあなたを設定することを願っています。


申し訳ありませんが、あなたの答えは正しくありません。はい、URLを変更できます。
デレク・朕會功夫

1
はい、html5履歴APIを使用できますが、URLのハッシュにフォールバックするポリフィルを使用できますが、クロスブラウザーではありません。
Jethro Larson

8

jQueryには、jQuery-pusherと呼ばれる、ブラウザーのURLを変更するための優れたプラグインがあります。

JavaScript pushStateとjQueryは、次のように一緒に使用できます。

history.pushState(null, null, $(this).attr('href'));

例:

$('a').click(function (event) {

  // Prevent default click action
  event.preventDefault();     

  // Detect if pushState is available
  if(history.pushState) {
    history.pushState(null, null, $(this).attr('href'));
  }
  return false;
});


状態を変更した後に作成されたXMLHttpRequestオブジェクトのHTTPヘッダーで使用されるリファラーを変更するJavaScript のみをhistory.pushState()使用します。

例:

window.history.pushState("object", "Your New Title", "/new-url");

pushState()メソッド:

pushState()状態オブジェクト、タイトル(現在は無視されます)、および(オプションで)URLの3つのパラメーターを取ります。これらの3つのパラメーターをそれぞれ詳しく見てみましょう。

  1. 状態オブジェクト —状態オブジェクトは、によって作成された新しい履歴エントリに関連付けられたJavaScriptオブジェクトpushState()です。ユーザーが新しい状態に移動すると、popstateイベントが発生し、イベントのstateプロパティに履歴エントリの状態オブジェクトのコピーが含まれます。

    状態オブジェクトは、シリアル化できるものであれば何でもかまいません。Firefoxは状態オブジェクトをユーザーのディスクに保存するため、ユーザーがブラウザーを再起動した後にそれらを復元できるため、状態オブジェクトのシリアル化された表現に640k文字のサイズ制限を課しています。シリアル化された表現がこれよりも大きい状態オブジェクトをに渡すpushState()と、メソッドは例外をスローします。これ以上のスペースが必要な場合は、sessionStorageまたはlocalStorage、あるいはその両方を使用することをお勧めします。

  2. title — Firefoxは現在このパラメータを無視していますが、将来使用する可能性があります。ここに空の文字列を渡すと、メソッドが将来変更されても安全です。または、移動先の州の短いタイトルを渡すこともできます。

  3. URL —新しい履歴エントリのURLは、このパラメーターによって指定されます。ブラウザはへの呼び出し後にこのURLのロードを試みませんpushState()が、たとえばユーザーがブラウザを再起動した後など、後でURLのロードを試みる可能性があることに注意してください。新しいURLは絶対的なものである必要はありません。相対である場合は、現在のURLを基準に解決されます。新しいURLは、現在のURLと同じオリジンである必要があります。そうでない場合、pushState()例外がスローされます。このパラメーターはオプションです。指定されていない場合は、ドキュメントの現在のURLに設定されます。



3

Facebookのフォトギャラリーは、URLに#ハッシュを使用してこれを行います。以下にいくつかのURLの例を示します。

「次へ」をクリックする前に:

/photo.php?fbid=496429237507&set=a.218088072507.133423.681812507&pid=5887027&id=681812507

「次へ」をクリックした後:

/photo.php?fbid=496429237507&set=a.218088072507.133423.681812507&pid=5887027&id=681812507#!/photo.php?fbid=496435457507&set=a.218088072507.133423.681812507&pid=5887085&id=681812507

ハッシュバング(#!)の直後に新しいURLが続くことに注意してください。



2

私のために働いているのは- history.replaceState()次のような機能です-

history.replaceState(data,"Title of page"[,'url-of-the-page']);

これはページをリロードしません、あなたはjavascriptのイベントでそれを利用できます


1

ページ内の親パスが同じである限り、何か新しいものだけが追加されるのではないかと考えていました。

つまり、ユーザーが ページにいるとhttp://domain.com/site/page.html しましょう。そうすると、ブラウザーで許可されlocation.append = new.html、ページは次のhttp://domain.com/site/page.htmlnew.htmlようになります。ブラウザーはそれを変更しません。

または、ユーザーがgetパラメータを変更できるようにするだけなので、しましょうlocation.get = me=1&page=1

なので元のページにhttp://domain.com/site/page.html?me=1&page=1なってリフレッシュしません。

#の問題は、ハッシュが変更されたときにデータがキャッシュされないことです(少なくとも私はそうは思いません)。つまり、新しいページが読み込まれるたびに、Ajax以外のページの[ 戻る]ボタンと[進む]ボタンはデータをキャッシュでき、データの再読み込みに時間を費やすことはありません。

私が見たところ、Yahooの歴史はすでにすべてのデータを一度にロードしています。Ajaxリクエストを実行していないようです。したがって、a divを使用してさまざまな方法で時間をかけて処理した場合、そのデータは履歴の状態ごとに保存されません。


1

私のコードは:

//change address bar
function setLocation(curLoc){
    try {
        history.pushState(null, null, curLoc);
        return false;
    } catch(e) {}
        location.hash = '#' + curLoc;
}

とアクション:

setLocation('http://example.com/your-url-here');

そして例

$(document).ready(function(){
    $('nav li a').on('click', function(){
        if($(this).hasClass('active')) {

        } else {
            setLocation($(this).attr('href'));
        }
            return false;
    });
});

それで全部です :)


1

私が提示するより簡単な答え、

window.history.pushState(null, null, "/abc")

これ/abcにより、ブラウザのURLのドメイン名の後に追加されます。このコードをコピーしてブラウザコンソールに貼り付け、URLが「https://stackoverflow.com/abc」に変わるのを確認してください


0

私は成功しました:

location.hash="myValue";

#myValue現在のURLに追加されるだけです。ページの読み込み時にイベントをトリガーする必要がある場合は、同じものlocation.hashを使用して関連する値を確認できます。たとえば#、によって返される値からを削除することを忘れないでくださいlocation.hash

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