pushState,popState,locationを利用する.hashなどの方法で小型ルーティングを実現


この記事は主にHTML 5でhistoryが提供するpushState,replaceState APIを記録している.最後に,これらのAPI自身により小型のルーティングを実現する.
Windowsについてhistoryが提供するAPIはMozillaドキュメントを参照
ここで、historyによって提供されるpushStateおよびreplaceStateの2つのAPIは、ブラウザ履歴スタックを操作する方法を提供する.
そのうちpushState:
    
    history.pushState(data, null, '#/page=1');
    
    pushState  3   ,        obj,     
    
          document.title  ,     `null`
    
         string,       url
pushStateメソッドは、urlを変更しながらブラウザ履歴スタックに新しい履歴を押し込む.
受信urlのパラメータは、現在のアドレスバーのurlを変更するためのstringのタイプである.このパラメータがドメイン間、すなわちプロトコル、ドメイン名、ポートと同じでなければならないことに注意してください.ドメイン間の状況が発生すると、プロンプトが表示されます.
Uncaught DOMException: Failed to execute 'pushState' on 'History': A history state object with URL 'http://www.baidu.com/' cannot be created in a document with origin 'http://commanderXL.com' and URL 


Example:
    
      www.baidu.com

    history.pushState(null, null, '?page=1')
    //      www.baidu.com/?page=1
    
    history.pushState(null, null, '#page=2');
    //      www.baidu.com/#page=2

そのうちreplaceState:
    history.replaceState(null, null, '#page=2');
replaceStateが受信したパラメータpushStateは同じであるが、最終的な効果は、アドレスバーurlは受信したパラメータに応じて変化するが、ブラウザは、ブラウズ履歴スタックにブラウザの履歴を追加するのではなく、現在のブラウザ履歴を置き換えることである.pushStatereplaceStateでURLを変更できますが、ブラウザreloadはアクティブにトリガーされません.windowオブジェクトはまた、popstateメソッドを提供する.
    window.addEventListener('popstate', function() {
        
    });

この方法は、ブラウザが異なる履歴で切り替えられ、対応するイベントがトリガーされるのを傍受するために使用される.
ブラウザが提供するhistoryオブジェクトには、ブラウザの前進後退ボタンをクリックするユーザをシミュレートするためのgobackの方法もある.あるウェブアプリケーションでは、例えばのラベルをクリックすると、ページのジャンプが発生します.このとき、history.back()が呼び出される.メソッド後にページがロールバックされ、ページがリフレッシュされると、window.onpopstateはこのイベントを傍受できません.ただし、pushStateまたはreplaceStateによってURLが変更され、ブラウザのリフレッシュが発生しない場合は、history.back()またはhistory.go()を使用すると、popstateイベントがトリガーされます.
    
    history.pushState({page: 1}, null, '?page=1');
    history.pushState({page: 2}, null, '?page=2');

    history.back(); //     

    window.addEventListener('popstate', function(e) {
        // popstate     ,    event               .
        //e.state   pushState   state   
        console.log(e.state);  //   {page: 1}
    });

PS:pushStateによってurlに?page=1を追加することで、location.searchによってsearchのコンテンツを取得することができる.ただし、location.searchurlを変更すると、ブラウザreloadがアクティブにトリガーされます.この特性は、hashに関する以下の内容と比較することができる.
APIは大体分かりましたが、これらの方法はどのような場所に応用できるのでしょうか.1つの比較的一般的なシナリオは、単一ページアプリケーションにおいて、これらのAPIによってフロントエンドのルーティング設計が完了し、pushStatereplaceStateを用いてurlを変更しながらブラウザがリフレッシュされず、popstateによってブラウザ履歴を傍受することによって、一連の非同期動作を完了することである.
    
    
    
    //  
    const Router = [];
    
    const addRoute = (path = '', handle = () => {}) => {
        let obj = {
            path,
            handle
        }
        
        Router.push(obj);
    }
    
    
    //      
    addRoute('/post', function() {
        //do something
    });
    
    addRoute('/login', function() {
        //do something
    })
    
    
    //    
    const routeHandle = (path) => {
        Router.forEach((item, index) => {
            if(item.path === path) {
                item.handle.apply(null, [path]);
                return true;
            }
        })
        return false;
    }
    
    
    //     a    
    document.addEventListener('click', function(e) {
        let dataset = e.target.dataset;
        if(dataset) {
            if(routeHandle(dataset.href)) {
                //      
                e.preventDefault();
            }
        }
    })

大まかな実装の構想は、によってルーティング情報を追加し、ラベルのデフォルトの動作をブロックし、登録されたルーティング情報と一致させることである.一致すると、対応するhandleのメソッドが呼び出される.
しかし、pushStatereplaceStateの方法は、低バージョンのIEブラウザで互換性があまりよくありません.したがって、ダウングレードは、hashを用いてルーティング設計を行うことができる.hash ?私を突いてください.location.hashにより、urlの最初の#(fragment)およびその後のコンテンツを取得することができる.また、location.hashによってコンテンツを書き換えることもでき、ブラウザreloadをアクティブにトリガーすることはありません.いくつかの機能はpushStatereplaceStateと同じですか?したがって、低バージョンのブラウザと互換性を持たせるために、#の変化を傍受することによってルーティング設計を行うことができる.
では、どうやって監視しますか?乱暴な方法の一つはpollingです.
    
    var oldHash = location.hash;
    setTimeInterval(function() {
        if(oldHash !== location.hash) {
            
            //do something
        
            oldHash = location.hash;
        }
    }, 100);

しかし、H 5はAPI:hashchangeも提供している.上記のpollingの方法に直接代わって、#の変化を傍受することができる.
    window.addEventListener('hashchange', function() {
        routeHandle(locaiton.hash);
    });

この小型のルーティング設計は私のgithubを参照することができます.
少しまとめてみます.
上では主にhistoryが提供するいくつかのAPI,hashに関する知識を紹介した.日常的にSPAに応用できるように,Gmailはhashによってルーティングを行う.ページジャンプに対して次のようになります.
  • ページは1回だけロードする必要があります.後のページ切り替えはajaxでデータを要求できます.ページ体験がよりスムーズになります.
  • は、ローカルキャッシュを使用してページ体験を最適化できます.異なるページの切り替えの過程でよりスムーズになります.
  • オンデマンド・ロード可能...

  • など実用的なメリットがあるでしょう.
    プロジェクトアドレス
    プロジェクトの住所を押してください.