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

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

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

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

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

  • 建立配置表(字符串路径和函数的映射)
  • 监听路由(onhashchange)
  • 处理路由变化,跟配置表的路径做匹配
    • 路径转化为正则表达式
    • 正则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]*))?$');
    }

从原来的:module2/: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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏DannyHoo的专栏

工程中导入第三方库RegexKitLite.h首先要做的。。。

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u010105969/article/details/...

502
来自专栏哈雷彗星撞地球

Xcode 调试技巧 --常用命令和断点

Xcode 中的调试技巧与我们的日常开发息息相关,而这些调试技巧在我们解决Bug时,常常有事半功倍的作用,经常会用到的有各种断点 和 命令。而这些调试技巧也经常...

782
来自专栏安恒网络空间安全讲武堂

writeup | 应该不是 XSS

0x01 初步分析阶段 首先拿到题目,看到留言板,第一反应就是XSS。 但是看过题目提示后,有些不确定。 所以开始分析整道题目。 首先,观察network页面,...

3936
来自专栏余生开发

base64图片转码

方法一: new fileReader().readAsDataURL(file) 方法二: var imgCanvas=document.createE...

732
来自专栏封碎

NDK入门、提高和实战 博客分类: Android AndroidLinuxJNIEclipseC#

    网上也有一些对NDK的介绍,不过都是很简单的把sample里面的例子讲解一下,并不深入,我这里把我的所得分享一下。我下载的是Android Native...

1066
来自专栏狂码一生

PHP获取客户端浏览器类型与版本函数封装应用

实现: /**  * 获取客户端浏览器类型  * @param  string $glue 浏览器类型和版本号之间的连接符  * @return string|...

3418
来自专栏Core Net

C# 处理Word自动生成报告 三、设计模板

2755
来自专栏崔庆才的专栏

使用Selenium爬取淘宝商品

3127
来自专栏MixLab科技+设计实验室

设计师编程指南之Sketch插件开发 1

发现网上关于sketch插件开发的指南太少了,而且都不一定可以成功运行,于是我就写了这个系列的文章: 1 我们需要了解的语法特点 sketch 是基于 Coc...

3508
来自专栏iOS开发攻城狮的集散地

Xcode常用快捷键

2066

扫码关注云+社区