标签:
在看了百度手机小说网站源码之后 突然兴起想自己实现一个基于网页hash技术的路由系统
源码 我放到oscgit上面了 地址: https://git.oschina.net/diqye/route.js
适用场景:
局部刷新页面 通过ajax局部刷新页面会有一个问题就是 分享url或者刷新页面时不能记录 当前网页的状态 前端路由可解决这个问题
期望的路由:
1 当访问网页 http://localhost/index.html 或者 http://localhost/index.html# http://localhost/index.html#/ 会触发如下代码中的fn
route.get(‘/‘,fn); fn的参数 req: 请求的信息 next如果后面有匹配的路由 调用该函数会继续匹配后面的路由
2 路径作为参数 当url改变为 http://localhost/index.html#2222/333 或者 http://localhost/index.html#/2222/333 期望把333传送给fn 当然路径中也支持*通配符
//number 只匹配数字
route.get(‘/2222/:number‘,function(req,next){
//req.para的值为333
});
//string 只匹配字符串
route.get(‘/2222/:string‘,function(req,next){
//req.para的值为333
});
3 全局拦截器 这个主要是对扩展的考虑
route.use(function(req,next){
//所有的路由变更都会经过此函数 如果不调用next函数路由不会往下匹配
console.log(‘1111‘);
next();
});
4 querystring 对象 当url为 http://localhost/index.html#?a=a&b=b 期望
route.get(‘/‘,function(req,next){
//req.query的值为 {a:‘a‘,b:‘b‘}
});
这个功能想通过拦截器来实现 比如
function querystring(req,next){
var query={};
//解析req.path 获取参数封装成对象 然后赋值给query
req.query=query;
next();
}
route.use(querystirng);
以上功能除了querystring 都实现了 关于路径匹配 还多加了俩个 支持 函数和正则 以下是代码 和测试代码 只测试了chrome浏览器
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Documeddddnddddddt</title>
</head>
<body>
<a href="#222/33/444">#222/33/444</a>
<a href="#111">#111</a>
<script type="text/javascript">
var TYPE=(function(){
var r={},types=[‘Arguments‘,‘Function‘,‘String‘,‘Number‘,‘Date‘,‘RegExp‘,‘Error‘,‘Null‘];
for(var i=0,t;t=types[i++];){
!function(t){
r[‘is‘+t]=function(obj){
return Object.prototype.toString.call(obj) === ‘[object ‘+t+‘]‘;
}
}(t)
}
return r;
})();
//前端路由 本来打算写成一个函数,但路由对象只需要全局存在一个即可 并没有发现需要多个对象存在的场景
var route=(function(){
var p={
//全局拦截器,本来想用链表来实现,但基于Javascript的特性用数组实现更加简单 和易用
headUseFns:[],
gets:[],
type:{
‘number‘:/^\d+$/,
‘string‘:/^[^\/]+$/,
‘date‘:/^[0-9]{6,6}$/
}
};
function getPath(url){
var path=url.split("#")[1];
if(!path)return "/";
if(path.charAt(0)!="/")path="/"+path;
return path;
}
function use(fn){
p.headUseFns.push(fn);
}
function hashchange(path){
var req={path:path},hlen=p.headUseFns.length;
if(hlen==0){
doother(req);
return;
}
//执行拦截器链
!function intec(i){
if(i==hlen){
doother(req);
return;
}
p.headUseFns[i](req,function(){
intec(i+1);
});
}(0);
}
function doother(req){
var path=req.path,hlen=p.gets.length;
var a=path.split(‘?‘);
if(a[1])path=a[0];
path=path.split(‘//‘).join(‘/‘);
if(path.charAt(path.length-1)==‘/‘)path=path.substr(0,path.length-1);
//执行拦截器链
!function intec(i){
if(i==hlen){
return;
}
if(p.gets[i].match(path,req)){
p.gets[i].fn(req,function(){
intec(i+1);
});
}else{
intec(i+1);
}
}(0);
}
function get(context,fn){
var match=null;
if(TYPE.isFunction(context))match=context;
else if(TYPE.isRegExp(context)){
match=function(path,req){
var para=context.exec(path);
if(para){
req.para=para;
}
return para;
}
}else if(TYPE.isString(context)){
match=stringmatch(context);
}
var getter={
match:match,
fn:fn
};
p.gets.push(getter);
}
function stringmatch(context){
var a=context.split(‘:‘),b=context.split(‘*‘);
if(a.length==1&&b.length==1){
return function(path,req){
return path==context;
}
}else if(a.length!=1){
var reg=p.type[a[1]];
if(reg==null)reg=new RegExp(a[1]);
return function(path,req){
var para=path.substr(a[0].length);
var r=path.indexOf(a[0])==0&®.test(para);
if(r)req.para=para;
return r;
}
}else if(b.length!=1){
return function(path,req){
return path.indexOf(b[0])==0;
}
}
}
function start(){
window.onhashchange=function(){
var path=getPath(location.href);
hashchange(path);
}
var path=getPath(location.href);
hashchange(path);
}
return {
start:start,
use:use,
get:get
}
})();
function querystring(req,next){
var query={};
//解析req.path 获取参数封装成对象 然后赋值给query 先不做
req.query=query;
next();
}
route.use(querystring);
route.use(function(req,next){
console.log(‘1111‘);
next();
});
route.use(function(req,next){
console.log(‘2222‘);
next();
});
route.get(‘/*‘,function(req,next){
console.log(‘/*‘,req);
next();
})
route.get(‘/:number‘,function(req){
console.log(‘/:number‘,req);
})
route.get(‘/:string‘,function(req){
console.log(‘/:string‘,req);
})
route.get(‘/222/*‘,function(req,next){
console.log(‘/222/*‘,req);
next();
});
route.get(‘/222/33/444‘,function(req,next){
console.log(‘/222/33/444‘,req);
next();
});
route.get(‘/222/33/:number‘,function(req,next){
console.log(‘/222/33/:number‘,req);
});
route.start();
</script>
</body>
</html>
这一小段代码 有一些小bug 我会在后续博文过程中去 修复
标签:
原文地址:http://my.oschina.net/diqye/blog/476286