usakdsteen

ゆうさくですてぃーん

ぶらうざ:ひすとりー

いくつかのサイトで

ページ遷移してないのにURLが変わったりしてて謎だったんだけど

謎じゃなくなった

 

URLの操作はwindow.locationやdocument.locationかと思ってたんだけど

locationはhash以外をいじるとページ遷移が発生しちゃってて、

location以外でURLいじる方法は何だ??と

今回もググらずMDNから検索して探すとかした(たぶんぐぐったほうが速かったとは思うが)

 

URLいじれる正体はこれだった

developer.mozilla.org

これの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>

 

初期状態

 

f:id:neetsdkasu:20200808051207p:plain

loadイベントのときh1タグの中身をLOADにして

history.stateがnullのとき緑色にする

このとき

Add Star ボタンをクリックすると

h1と同色である緑の★が追加されて、h1が赤のBUTTONに変わる

f:id:neetsdkasu:20200808051421p:plain

続けてAdd Starをクリックすると

h1と同色である赤の★が追加されて、h1がシアン色になる

f:id:neetsdkasu:20200808051519p:plain

同様にAdd Starクリックしまくるとh1の色の★が追加されてh1の色が変わる

 

f:id:neetsdkasu:20200808051631p:plain

ここでブラウザの戻るを3回くらい押すと

h1がシアン色になって文字がPOPSTATEになる

f:id:neetsdkasu:20200808051721p:plain

 進むを押すとh1が黄色になる

f:id:neetsdkasu:20200808051757p:plain

Add Star押せば黄色の★が追加されh1が茶のBUTTONに変わる

f:id:neetsdkasu:20200808051827p:plain

ここでブラウザの再読込ボタンを押すと

h1文字が茶色のLOADになって★が全部消える

f:id:neetsdkasu:20200808051959p:plain

★が消えたのはページがリセットされたからだけど、h1の文字が緑色ではなく茶色になったのはpushStateで茶色の情報を保存してたから、そこの部分は復元できたということ(★の状態を保存や復元するコードは書いてないため消えたまま)

さらに戻るボタンを押すとh1が黄色のPOPSTATEになる(pushStateでつっこんだ情報の履歴から復元できてる

f:id:neetsdkasu:20200808052041p:plain

戻るボタン押してh1をシアン色にして

f:id:neetsdkasu:20200808052611p:plain

Add Starを押す

f:id:neetsdkasu:20200808052642p:plain

ここでhashのリンクを踏むと

何故かPOPSTATEが呼び出され、stateなしゆえ緑色になって、でも★は消えてないという、謎の状態になった

f:id:neetsdkasu:20200808052807p:plain

★が消えてないってことはページ遷移が発生したわけではなく、

状態変化が起きたっていうpopstateが発生して、ブラウザの閲覧履歴にはハッシュ付きのURLが生えてるという感じだと思う

pushStateしたわけじゃないからstateがnullなのだと思う、stateがnullのとき緑色になるようにしたから…