Help us understand the problem. What is going on with this article?

JavaScriptでURLを操作するメモ

More than 5 years have passed since last update.

なんか難しくって忘れそうなのでメモっておきます。

history.pushState(state, title, url)

履歴に指定したURLを追加するってこと。指定したURLへの再読み込みは発生しないので、読み込みの処理は自分で行う。

hoge.comのページでhoge.com/hogeにしたい場合

history.pushState(null,null,"/hoge");

こうするとブラウザのURL欄がhoge.com/hogeに変わる。けどページには何も変化が起こらない。
pushStateするとブラウザのURL履歴が追加される。わかりやすく説明すると

history.pushState(null,null,"/hoge1");
history.pushState(null,null,"/hoge2");
history.pushState(null,null,"/hoge3");

このように履歴を3回追加したあとに、ブラウザの戻るボタンをクリックしていくと

"hoge.com/hoge3"->"hoge.com/hoge2"->"hoge.com/hoge1"-> "hoge.com"

の順に、ブラウザのURL欄が変わっていきます。このときやはりページの内容は変わりません。

さらにhoge.comまで戻った後にブラウザの進むボタンをクリックすると

"hoge.com"->"hoge.com/hoge1"->"hoge.com/hoge2"-> "hoge.com/hoge3"

の順に、ブラウザのURL欄が変わっていきます。
しつこいようですが、ページの内容は変わりません。

history.repalceState(state, title, url)

現在の履歴が書き換えられます
要は履歴に追加されないってこと。

hoge.comの状態で下記を実行すると

history.relpaceState(null,null,"/hoge1");

アドレス欄がhoge.com/hoge1に変わりますが、ブラウザの戻るボタンを押しても
一つ前のhoge.comには戻りません。hoge.comを見ていた前の履歴のアドレスが表示されます。
見た目の履歴上は、hoge.comには行っていないことになります。

もうサルでもわかるように説明すると。(サルな自分に説明すると・・)

history.pushState(null,null,"/hoge1"); //ブラウザのURL欄はhoge.com/hoge1
history.pushState(null,null,"/hoge2");//ブラウザのURL欄はhoge.com/hoge2
history.replaceState(null,null,"/hoge3");//ブラウザのURL欄はhoge.com/hoge3
history.pushState(null,null,"/hoge4");//ブラウザのURL欄はhoge.com/hoge4

このように3回目にreplaceStateを実行したとします。
さて、ブラウザの戻るボタンを押すとどうなるでしょう?

現在のURLは hoge.com/hoge4です。
1回目 ブラウザのURL欄はhoge.com/hoge3 になります。
2回目 ブラウザのURL欄はhoge.com/hoge1 になります。

というわけでhoge2には行っていないように見えます。
今度は進むボタンを押すと
html
現在のURLは hoge.com/hoge1です。
1回目 ブラウザのURL欄はhoge.com/hoge3 になります。
2回目 ブラウザのURL欄はhoge.com/hoge4 になります。

このようにhoge2は出てきません。

第一引数State

ここまでnullで無視してきた第一引数ですが、これはなんでしょうか?
検索すると

履歴に関連付する任意のオブジェクトを渡すことができ、そのオブジェクトはpopstateイベントハンドラから参照することができます。

????
サルでもわかるよう解説すると(サルな自分に・・・)

window.onpopstate=function(e)
       console.log(e.state);
}
//現在のURLはhoge.com
history.pushState("hello",null,"/hoge1");

この状態でブラウザの戻る、進むボタンを押してみてください。
進むボタンを押した後に、ブラウザのコンソールで見ると
helloと表示されると思います。stateは、こんな感じでページ遷移時のイベントハンドラに渡されます。また、history.stateでもアクセスできます。
詳しくは下で解説

popState

これで最後。
これはpushState後にブラウザの戻る、進むを行った場合のイベント取得するために使用します。

前述の通り、pushStateや、pushState後の戻る、進むボタンではページ内容が
変わりませんでしたよね。
pushStateの場合、pushStateを実行したときにページを読み込む処理を書けばよいですが、
ブラウザの戻るや進むボタンを使った場合には、このpopStateイベントで捕まえて
ページを書き換える必要があるわけです

//本当はwindow読み込み時に処理するけど省略
window.onpopstate=function(e){
       どこの解説にも書いてあるので一応いれとく
       if (!e.originalEvent.state) return; // 初回アクセス時に再読み込みしてしまう対策
       //ページ読み込み、描画処理
       ・・・・
}

こんな感じですかね。
ちなみに現在のパスはlocation.pathname、クエリはlocation.searchなんかで取得できあすので、これを使って現在のURL応じたページ描画処理を行います。

あと、ブラウザの戻る、進むをjavascirptで処理する場合は
戻る:history.back()
進む:history.forward()

を使います。
これらの関数呼び出し後も同様に、popStateイベントが発生します。

※HTML5以降の実装なので、古いブラウザだと使えません。

以上、自分はこれでだいたい理解しました。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした