アリババ校招2017フロントエンド筆記試験テーマ--原生js/html 5実現一つのルート


アリババ校招2017フロントエンド筆記試験テーマ:1)ルートにはどんな欠点がありますか?2)原生js/html 5は一つのルートを実現する
欠点:*ブラウザの前進を使用して、後退キーの時再び要求を発送することができて、合理的にキャッシュ*単ページを利用して前にスクロールした位置を覚えることができなくて、前進することができなくて、後退する時にスクロールした位置を覚えることができません
ルーティングの概念:*ルーティングは異なるurlアドレスに基づいて異なるコンテンツまたはページを示す*フロントエンドルーティングは、異なるルーティングに対応する異なるコンテンツまたはページのタスクをフロントエンドに渡すことであり、以前はサービス側がurlの違いに基づいて異なるページを返すことによって実現されていた.
2つの例を直接見てみましょう.1つはhash構造で、これはHtml 5のhistory apiが現れる前の解決策です.1つはhistory apiに基づいて実現される.-hash
http://10.0.0.1/
http://10.0.0.1/#/about
http://10.0.0.1/#/concat
  • history
  • http://10.0.0.1/
    http://10.0.0.1/about
    http://10.0.0.1/concat

    フロントエンドのルーティングとバックエンドのルーティングは実装技術的に異なるが,原理は同じである.
    1.hash
    肝心なのは2つのイベントを監視することで、1つはページがロードされたときにトリガーload、もう1つはhashが変更されたときにトリガーhashchangeです.
    
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <title>Documenttitle>
    head>
    <body>
        <ul>
            <li><a href="#/">turn whitea>li>
            <li><a href="#/blue">turn bluea>li>
            <li><a href="#/green">turn greena>li>
        ul>
        <script>
        class Router {
            constructor() {
                this.routes = {};
                this.curUrl = "";
            }
            route(path, callback) {
                this.routes[path] = callback || function() {};
            }
            refresh() {
                this.curUrl = location.hash.slice(1) || '/';
                this.routes[this.curUrl]();
            }
            init() {
                window.addEventListener('load', this.refresh.bind(this), false);
                window.addEventListener('hashchange', this.refresh.bind(this), false);
            }
    
        }
        var router = new Router();
        router.init();
        var content = document.querySelector('body');
        // change Page anything
        function changeBgColor(color) {
            content.style.backgroundColor = color;
        }
        router.route('/', function() {
            changeBgColor('white');
        });
        router.route('/blue', function() {
            changeBgColor('blue');
        });
        router.route('/green', function() {
            changeBgColor('green');
        });
        script>
    body>
    
    html>
    

    2.history api
    html 5には、pushStatereplaceStateの2つの方法が追加する.
    2つのメソッドには、3つのパラメータがあります.1つのステータスオブジェクト、1つのタイトル(無視されます)、1つのオプションのURLアドレスステータスオブジェクト(state object)-pushState()メソッドで作成された新しい履歴エントリに関連付けられたJavaScriptオブジェクトです.ユーザーが新しく作成したステータスにナビゲートするたびにpopstateイベントがトリガーされ、イベントオブジェクトのstateプロパティには履歴エントリのステータスオブジェクトのコピーが含まれます.
    シーケンス可能なオブジェクトは、ステータスオブジェクトとして使用できます.FireFoxブラウザはステータスオブジェクトをユーザーのハードディスクに保存するので、ユーザーがブラウザを再起動した後に復元することができ、ステータスオブジェクトのサイズを640 kに強制的に制限します.PushState()メソッドに限度額を超えるステータスオブジェクトを渡すと、メソッドは例外を放出します.大きなデータを格納する必要がある場合は、sessionStorageまたはlocalStorageを使用することをお勧めします.
    pushStateはhistoryに現在のページのレコードを追加するために使用されますが、replaceStateとpushStateの使用方法はまったく同じで、現在のページのhistoryでのレコードを変更するために使用される唯一の違いがあります.
    両者の1つの表現の違いは、ブラウザで後退ボタンをクリックした場合、pushStateを使用すると正常にクリック順に戻ってくるが、replaceStateを使用するのは置き換えだけで、戻ってこず、pushStateの記録に直接戻ることである.
    index.html
    
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Simple Historytitle>
    head>
    <body>
        <a class="push" href="?push-one">Push Onea>
        <a class="push" href="?push-two">Push Twoa>
        <a class="push" href="?push-three">Push Threea>
        <a class="replace" href="?replace-one">Replace Onea>
        <a class="replace" href="?replace-two">Replace Twoa>
        <a class="replace" href="?replace-three">Replace Threea>
        <ul id="log">ul>
        <script src="simple-history.js">script>
        <script src="https://cdn.bootcss.com/jquery/1.7.1/jquery.min.js">script>
        <script>
        (function() {
            if (!SimpleHistory.supported) {
                return;
            }
            SimpleHistory.start(function(path) {
                console.log("match", path);
                document.title = "Simple History - " + path;
                $("
  • "
  • ).text("match: " + path).appendTo("#log"); }); $("a:not([href^=http])").click(function(event) { if (event.metaKey || event.shiftKey || event.ctrlKey) { return; } event.preventDefault(); var path = $(event.target).attr("href"); if ($(event.target).is(".push")) { SimpleHistory.pushState(event.target.href); } else { SimpleHistory.replaceState(event.target.href); } }); }())
    script> body> html>

    ** simple-history.js**
    (function(window, undefined) {
    
        var initial = location.href;
    
        window.SimpleHistory = {
            supported: !!(window.history && window.history.pushState),
            pushState: function(fragment, state) {
                state = state || {};
                history.pushState(state, null, fragment);
                this.notify(state);
            },
            replaceState: function(fragment, state) {
                state = state || {};
                history.replaceState(state, null, fragment);
            },
            notify: function(state) {
                console.log(location.pathname,location.search);
                this.matcher(location.pathname + location.search, state);
            },
            start: function(matcher) {
                this.matcher = matcher;
                window.addEventListener("popstate", function(event) {
                    // workaround to always ignore first popstate event (Chrome)
                    // a timeout isn't reliable enough
                    if (initial && initial === location.href) {
                        initial = null;
                        return;
                    }
                    SimpleHistory.notify(event.state || {});
                }, false);
            }
        };
    
    }(window));

    参考阅读:-原生のJSは1つの简単なフロントエンドのルート(ルートの実现の原理)を実现します-React Routerからルートのあれらの事を话します