JavaScript/ブラウザ操作/履歴操作

JavaScript/ブラウザ操作/履歴操作

URLを貼り替える

以前のブラウザでは URL に対する制御に関してJSは介入できなかった。 URL を書き換えてしまうと本当にその URL へ遷移してしまっていた。 なので、♯を使ったページ内リンクを用いてURLとパラメータを結びつけた挙動を実現していた。

が、今は history API を使うことで URL とブラウザの挙動をまったく関係なく制御が可能になっている。

現在 http://localhost/index.html に居るとして、↓のコードが実行されると

history.pushState({aaa: "えー"}, "hogehoge", "hoge.html");

ブラウザの挙動としてはなんにも起きてないのだが、URL だけが http://localhost/hoge.html に貼り変わる。

第一引数は、この history に紐付けるstateオブジェクトで、履歴を巡る時に取り出せるようになっている。 第二引数は、title らしいのだが実装されているか不明。 最後がURLでこの URL になり、履歴にこの URL が追加される。

ではこのstate を取り出すにはこのようにフックしておく

window.addEventListener("popstate", (e)=>{
    console.log(e.state);
});

index.html から pushState のコードが実行されて hoge.html へ貼り変わる。 ここでブラウザの戻るボタンを押すと、↑でフックしている popstate イベントが発火する。 そして URL が index.html に貼り変わる。しかし何かがリロードされるわけもなく単に貼り変わるだけ。 index.html に対しては state は設定されていないのでここでの console 出力は null になる。

次にブラウザの進むで再び hoge.html に遷移するとまた popstate イベントが発火する。 hoge.html に対しては state オブジェクトがあるので pushState で指定したオブジェクトが取り出せる

この state オブジェクトは参照値なのか、それとも値として保持されるのか問題であるが、 この pushState で登録されるオブジェクトは、内部では登録された時点の状態で clone されて保持されるようだ。 なので参照を通じて書き換えても登録された内容は変わらない。つまり参照ではない。

逆に state オブジェクト内部に関数のようなその時点で値が確定できないようなモノを含む場合そもそも登録できない。

pop して取り出すことができる state は push した時点の状態ではなく、その画面が描画された時点の状態が入っていると想定されている。

遷移直前に push して遷移するのだが、この直前状態というのは直後状態を指している(直前にその後の外観を作るのだからこの時点で直後の状態を知っているのは正しい)。 なので直後状態から戻るで pop が発生すると取得する state は実際には 1つ前ではなく 2つ前の state を指すことになる。

なので、描画 → push → 遷移 → 戻る とすると state が null になる。

つまり、最初のローディング描画直後の state が必要になるということ。

ここでさらに考えないといけないのは、ローディング時の履歴はロード完了時にもうすでに history に入っていて、そいつに対して状態を保存しなければならない。 なのでここでは pushState ではなく replaceState を使う

このようになる。

history.replaceState({hogehoge: "ほげほげ"}, '');

第1引数には状態、第2引数には title らしいが現状動作しない、第3引数を省略すると現状の history の書き換えになり遷移も発生しない。

なので、 ロード、描画、replace, push, 描画, 戻る での pop で replace で設定した state つまり1つ前の画面での状態が取り出せる。

javascript/browser_ope/history/start.txt · 最終更新: 2020-09-09 14:48 by ore