router.js
3.28 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
/**
* Created by kenkozheng on 2015/7/16.
* 利用backbone的路由语法,建立极简,适用于手机浏览器的路由
* 增加了*号路由,等于backbone的defaultAction
*/
define(
'mk7/router',
[
],
function() {
var router = {
init: function (map) {
var defaultAction = map['*'];
if(defaultAction){
router.defaultAction = defaultAction;
delete map['*'];
}
router.routes = map;
init();
onchange();
},
routes: {},
defaultAction: null
};
function onchange(onChangeEvent){
var newURL = onChangeEvent && onChangeEvent.newURL || window.location.hash;
var url = newURL.replace(/.*#/, '');
var found = false;
for (var path in router.routes) {
var reg = getRegExp(path);
var result = reg.exec(url);
if(result && result[0] && result[0] != ''){
var handler = router.routes[path];
handler && handler.apply(null, result.slice(1));
found = true;
}
}
if(!found && router.defaultAction){
router.defaultAction();
}
}
/**
* 引自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]*))?$');
}
/**
* 这段判断,引用于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');
}
}
return router;
}
);