前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >一个类似backbone路由的纯净route ( 前端路由 客户端路由 backbone路由 )

一个类似backbone路由的纯净route ( 前端路由 客户端路由 backbone路由 )

作者头像
用户1258909
发布2018-07-03 14:52:23
1K0
发布2018-07-03 14:52:23
举报
文章被收录于专栏:拂晓风起拂晓风起

大家用backbone、angular,可能都习惯了内置的路由,这两个框架的路由都是非常优秀的,强大而简单。

客户端(浏览器)路由原理其实比较简单,其实就是监听hash的变化。

在之前的架构探讨中,说到director.js这个路由类库不好使,那么,在这一篇,我们尝试自行实现一个简洁而且非常好使的路由类库。

原理先介绍,无非几个步骤:

  • 建立配置表(字符串路径和函数的映射)
  • 监听路由(onhashchange)
  • 处理路由变化,跟配置表的路径做匹配
    • 路径转化为正则表达式
    • 正则exec,匹配+抽取参数

其中难点就在于路径转化为正则表达式,director没做好就是这一步,而backbone则做得非常非常强大,那么我们可以尝试把backbone这一块代码抠出来。

路由表:

代码语言:javascript
复制
    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
    };

监听路由变化:

代码语言:javascript
复制
    /**
     * 这段判断,引用于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');
        }
    }

处理路由变化,先拼凑正则表达式:

代码语言:javascript
复制
    /**
     * 引自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]*))?$');
    }

从原来的:module2/:name变成标准的正则表达式,个中奥妙大家自行顿悟

循环匹配:

代码语言:javascript
复制
    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();
        }
    }

然后。。。做个简单的测试:

代码语言:javascript
复制
<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

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2015-07-16 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档