一个类似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
一个类似backbone路由的纯净route ( 前端路由 客户端路由 backbone路由 )的更多相关文章
- socket 实现一个类似简单聊天室的功能(多客户端互相通信)
server端: #coding=utf-8 ''' 一个广播程序,linux运行 ''' import select,socket import traceback def broadcast(co ...
- vue+axios 前端实现登录拦截(路由拦截、http拦截)
一.路由拦截 登录拦截逻辑 第一步:路由拦截 首先在定义路由的时候就需要多添加一个自定义字段requireAuth,用于判断该路由的访问是否需要登录.如果用户已经登录,则顺利进入路由, 否则就进入登录 ...
- 【转】vue+axios 前端实现登录拦截(路由拦截、http拦截)
一.路由拦截 登录拦截逻辑 第一步:路由拦截 首先在定义路由的时候就需要多添加一个自定义字段requireAuth,用于判断该路由的访问是否需要登录.如果用户已经登录,则顺利进入路由, 否则就进入登录 ...
- Angular入门到精通系列教程(13)- 路由守卫(Route Guards)
1. 摘要 2. 路由守卫(Route Guards) 2.1. 创建路由守卫 2.2. 控制路由是否可以激活 2.3. 控制路由是否退出(离开) 3. 总结 环境: Angular CLI: 11. ...
- Web Api通过Route、RoutePrefix等特性设置路由
[Route("customers/{customerId}/orders")] [HttpGet] public IEnumerable<Order> FindOrd ...
- 每天一个Linux命令(47)route命令
Linux系统的route命令用于显示和操作内核IP路由表(show / manipulate the IP routing table). (1)用法: 用法: route ...
- react 中的路由 Link 和Route和NavLink
route是配置,link是使用 https://blog.csdn.net/chern1992/article/details/77186118(copy) 嵌套路由一般使用Route,类似于vue ...
- 路由配置(route IP
转载于:http://blog.csdn.net/chenlycly/article/details/52141854 使用下面的 route 命令可以查看 Linux 内核路由表. # route ...
- 路由信息相关 route 网卡
目录 route命令 1.查看路由表 2.管理路由 基本网络配置 添加网卡地址 修改网卡UUID route命令 路由表管理命令,路由表主要构成: Destination: 目标网络ID,表示可以到达 ...
随机推荐
- 解决jquery和prototype库冲突问题
在项目中同时引入了jquery.js和prototype.js两个文件,在方法调用时启了冲突. 我们在使用 jQuery 的过程中我们会频繁使用 $ 符号,$是JQuery的别名,所有使用$的地方也都 ...
- [Node.js] 基于Socket.IO 的私聊
原文地址:http://www.moye.me/2015/01/02/node_socket-io/ 引子 最近听到这么一个问题:Socket.IO 怎么实现私聊?换个提法:怎么定位到人(端),或者说 ...
- Pillow实现图片对比
在编写Web自动化测试用例的时候,如何写断言使新手不解,严格意义上来讲,没有断言的自动化脚本不能叫测试用例.就像功能测试一样,当测试人员做了一些操作之后必然会判断实际结果是否等于预期结果,只不过,这个 ...
- CSS Vocabulary – CSS 词汇表,你都掌握了吗?
CSS 是前端开发必备技能,入门容易,深入难.比如像 Pseudo-class.Pseudo-element.Media query.Media type 以及 Vendor prefix 的概念,很 ...
- linux专题一之文件管理(目录结构、创建、查看、删除、移动)
在linux系统中一切都是文件./ 在linux中为根目录,是一切文件的根目录.本文将通过linux系统的目录结构和与linux文件操作有关的相关命令(touch.mkdir.cp.mv.mv.les ...
- iOS开发的一些奇巧淫技
TableView不显示没内容的Cell怎么办? 类似这种,我不想让下面那些空的显示. 很简单. self.tableView.tableFooterView = [[UIView alloc] in ...
- linux service命令解析
我们平时都会用service xxx start来启动某个进程,那么它背后究竟执行了什么? 其实service的绝对路径为/sbin/service ,打开这个文件cat /sbin/servic ...
- 30天C#基础巩固------读写流(StreamWrite/StreamReader)
一:读写流的一些案例. --->关于StreamWrite 这里的一些常用的方法和我们之前的那个FileStream是一样的,参数很多都是一样的用法. Console.WriteLi ...
- C语言学习004:数组与指针
在C语言中,字符串实际上就是字符数组,在内存中字符串"Shatner"存储的形式是这样的
- 速战速决 (1) - PHP: 概述, 常量, 变量, 运算符, 表达式, 控制语句
[源码下载] 速战速决 (1) - PHP: 概述, 常量, 变量, 运算符, 表达式, 控制语句 作者:webabcd 介绍速战速决 之 PHP 概述 常量 变量 运算符 表达式 控制语句 示例1. ...