いくつかのサイトで
ページ遷移してないのにURLが変わったりしてて謎だったんだけど
謎じゃなくなった
URLの操作はwindow.locationやdocument.locationかと思ってたんだけど
locationはhash以外をいじるとページ遷移が発生しちゃってて、
location以外でURLいじる方法は何だ??と
今回もググらずMDNから検索して探すとかした(たぶんぐぐったほうが速かったとは思うが)
URLいじれる正体はこれだった
これのhistory.pushState()やhistory.replaceState()でURLをいじれるということが分かった
これは要するにページ遷移なしでページの状態とURLのパスとを関連づけたい連動させたい、っていう感じの使い方をするものっぽい
ブラウザの戻るボタンや進むボタンやリロードなどでページの状態を復元できる、みたいな仕組みぽい
一応、挙動の確認をお試した
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>test</title>
</head>
<body>
<h1>History?</h1>
<hr>
<button>Add Star</button>
<div id="stars"></div>
<hr>
<div>move to: <a href="https://www.google.com/" rel="noreferrer nofollow">google.com</a></div>
<hr>
<div><a href="#">hash</a></div>
<div><button onclick="window.location.reload();">reload</button></div>
<script>
function colored(t) {
return () => {
const cs = history.state;
const h = document.querySelector('h1');
if (cs === null) {
h.style.color = 'green';
} else {
h.style.color = cs.color;
}
h.textContent = t.toUpperCase();
};
}
window.addEventListener('load', colored('load'));
window.addEventListener('popstate', colored('popstate'));
document.querySelector('button')
.addEventListener('click', () => {
const cs = history.state;
let color = 'green';
if (cs !== null) {
color = cs.color;
}
const span = document.querySelector('#stars')
.appendChild(document.createElement('span'));
span.style.color = color;
span.textContent = '★';
switch (color) {
case 'green': color = 'red'; break;
case 'red': color = 'cyan'; break;
case 'cyan': color = 'yellow'; break;
case 'yellow': color = 'brown'; break;
case 'brown': color = 'blue'; break;
case 'blue': color = 'magenta'; break;
case 'magenta': color = 'lime'; break;
default: color = 'red'; break;
}
history.pushState({"color": color }, '', `${window.location.pathname}?color=${color.toUpperCase()}`);
colored('button')();
});
</script>
</body>
</html>
初期状態
loadイベントのときh1タグの中身をLOADにして
history.stateがnullのとき緑色にする
このとき
Add Star ボタンをクリックすると
h1と同色である緑の★が追加されて、h1が赤のBUTTONに変わる
続けてAdd Starをクリックすると
h1と同色である赤の★が追加されて、h1がシアン色になる
同様にAdd Starクリックしまくるとh1の色の★が追加されてh1の色が変わる
ここでブラウザの戻るを3回くらい押すと
h1がシアン色になって文字がPOPSTATEになる
進むを押すとh1が黄色になる
Add Star押せば黄色の★が追加されh1が茶のBUTTONに変わる
ここでブラウザの再読込ボタンを押すと
h1文字が茶色のLOADになって★が全部消える
★が消えたのはページがリセットされたからだけど、h1の文字が緑色ではなく茶色になったのはpushStateで茶色の情報を保存してたから、そこの部分は復元できたということ(★の状態を保存や復元するコードは書いてないため消えたまま)
さらに戻るボタンを押すとh1が黄色のPOPSTATEになる(pushStateでつっこんだ情報の履歴から復元できてる
戻るボタン押してh1をシアン色にして
Add Starを押す
ここでhashのリンクを踏むと
何故かPOPSTATEが呼び出され、stateなしゆえ緑色になって、でも★は消えてないという、謎の状態になった
★が消えてないってことはページ遷移が発生したわけではなく、
状態変化が起きたっていうpopstateが発生して、ブラウザの閲覧履歴にはハッシュ付きのURLが生えてるという感じだと思う
pushStateしたわけじゃないからstateがnullなのだと思う、stateがnullのとき緑色になるようにしたから…