backboneルーティングのような純粋なroute(フロントエンドルーティングクライアントルーティングbackboneルーティング)

9100 ワード

backbone、angularは、内蔵のルーティングに慣れているかもしれませんが、この2つのフレームワークのルーティングは非常に優れており、強くて簡単です.
クライアント(ブラウザ)のルーティング原理は簡単で、hashの変化を傍受することです.
以前のアーキテクチャの検討ではdirectorについて述べた.jsというルーティングクラスライブラリは使いにくいので,本稿では,簡潔で非常に使いやすいルーティングクラスライブラリを独自に実現しようと試みる.
 
原理はまず紹介され、いくつかのステップにほかならない.
  • コンフィギュレーションテーブル(文字列パスと関数のマッピング)
  • を確立する
  • リスニングルーティング
  • ルーティングの変更を処理し、構成テーブルのパスと一致する
  • パスを正規表現
  • に変換
  • 正規exec、マッチング+抽出パラメータ

  •  
    難点は経路が正規表現に変換されたことであり、directorがうまくいかなかったのはこのステップであり、backboneは非常に強力であるので、backboneというコードをほじくり出してみることができます.
     
    ルーティングテーブル:
        var Route = root.Route = {
            init: function (map) {
                var defaultAction = map['*'];
                if(defaultAction){
                    Route.defaultAction = defaultAction;
                    delete map['*'];
                }
                Route.routes = map;
                init();
                onchange();
            },
            routes: {},
            defaultAction: null
        };

     
    経路変更のリスニング:
        /**
         *     ,   director:https://github.com/flatiron/director
         */
        function init(){
            if ('onhashchange' in window && (document.documentMode === undefined
                || document.documentMode > 7)) {
                // At least for now HTML5 history is available for 'modern' browsers only
                if (this.history === true) {
                    // There is an old bug in Chrome that causes onpopstate to fire even
                    // upon initial page load. Since the handler is run manually in init(),
                    // this would cause Chrome to run it twise. Currently the only
                    // workaround seems to be to set the handler after the initial page load
                    // http://code.google.com/p/chromium/issues/detail?id=63040
                    setTimeout(function() {
                        window.onpopstate = onchange;
                    }, 500);
                }
                else {
                    window.onhashchange = onchange;
                }
                this.mode = 'modern';
            } else {
                throw new Error('sorry, your browser doesn\'t support route');
            }
        }

     
    ルーティングの変更を処理し、正規表現をまとめます.
        /**
         *   backbone,       
         * @param route
         * @returns {RegExp}
         */
        function getRegExp(route){
            var optionalParam = /\((.*?)\)/g;
            var namedParam    = /(\(\?)?:\w+/g;
            var splatParam    = /\*\w+/g;
            var escapeRegExp  = /[\-{}\[\]+?.,\\\^$|#\s]/g;
            route = route.replace(escapeRegExp, '\\$&')
                .replace(optionalParam, '(?:$1)?')
                .replace(namedParam, function(match, optional) {
                    return optional ? match : '([^/?]+)';
                })
                .replace(splatParam, '([^?]*?)');
            return new RegExp('^' + route + '(?:\\?([\\s\\S]*))?$');
        }

    元の:module 2/:nameから標準的な正則表現になり、その奥義をみんなが悟る
     
    循環一致:
        function onchange(onChangeEvent){
            var newURL = onChangeEvent && onChangeEvent.newURL || window.location.hash;
            var url = newURL.replace(/.*#/, '');
            var found = false;
            for (var path in Route.routes) {
                var reg = getRegExp(path);
                var result = reg.exec(url);
                if(result && result[0] && result[0] != ''){
                    var handler = Route.routes[path];
                    handler && handler.apply(null, result.slice(1));
                    found = true;
                }
            }
            if(!found && Route.defaultAction){
                Route.defaultAction();
            }
        }

     
    そして...簡単なテストを行います.
    <script src="libs/backbone-route.js"></script>
    <script>
    
        Route.init({
            'module1': function(){
                console.log(1);
            },
            'module2/:name/:age': function(){
                console.log(2, arguments);
            },
            'module3(/:name)(/:age)': function(){
                console.log('3', arguments);
            },
            '*': function(){
                console.log(404);
            }
        });
    </script>

     
     
    この文書のコード:https://github.com/kenkozheng/HTML5_research/tree/master/backbone-route