2

我正在考虑在 javaScript 中构建一个超级简单的路由器......到目前为止我有这个:

var match,routeMatcher,p;

var routes = {
    "/users/:uid/pictures/:uid" : "userpictures",
    "/users/:uid" : "user"
};

var url = "/users/1024/pictures/456";

for(var i in routes) {
    //need to cache this regex
    routeMatcher = new RegExp(i.replace(/:[^\s/]+/g, '([\\w-]+)'));
    if(url.match(routeMatcher)) {
        match = url.match(routeMatcher);
        p = routes[i];
        console.log(p);
    }
}

这是一个小提琴http://jsfiddle.net/D6txe/

这行得通。当我输入像“users/1000”这样的 url 时,我会返回相应的函数名称(现在只需弄清楚如何将字符串作为函数调用)。问题是如果我有两条非常相似的路线,就像我的示例中的正则表达式匹配两者一样。在上面的示例中,理想情况下,我只希望匹配第二条路线,但不幸的是两者都匹配,因为当然第一条路线也是匹配的。

有什么办法可以让正则表达式只返回完全匹配?我有另一个解决方案,它涉及计算输入 url 中的正斜杠,并且只调用具有匹配数量的正斜杠的路由......但这似乎相当不雅。

4

3 回答 3

4

Try this:

routeMatcher = new RegExp(i.replace(/:[^\s/]+/g, '([\\w-]+)') + "$");

If you also want to support a trailing / to also cover /users/1024/pictures/456/, you can change your RegExp as follows:

routeMatcher = new RegExp(i.replace(/:[^\s/]+/g, '([\\w-]+)') + "/?$");
于 2012-12-19T10:27:43.810 回答
2

这是一个缓存正则表达式的变体(注意正则表达式中的'^'and '$'):

function Router(routes) {
    var route, routeExp, matchers = {};

    for (route in routes) {
        if (routes.hasOwnProperty(route)) {
            routeExp = '^' + route.replace(/:[^\s/]+/g, '([\\w-]+)') + '$';
            matchers[route] = new RegExp(routeExp);
        }
    }

    return function(url) {
        var match;
        for (route in matchers) {
            if (matchers.hasOwnProperty(route)) {
                if (match = url.match(matchers[route])) {
                    return {
                        route: route,
                        name: routes[route],
                        match: match.slice(1)
                    };
                }
            }
        }
    }
}

用法:

var router = new Router({
    "/users/:uid/pictures/:uid" : "userpictures",
    "/users/:uid" : "user"
});

var result = router("/users/1024/pictures/456");

console.log(result);
/*
{
    route: "/users/:uid/pictures/:uid",
    name: "userpictures"
    match: ["1024", "456"]
}
*/
于 2012-12-19T11:46:40.637 回答
2

我不完全确定这是否是您需要的。

我使用^and$使正则表达式与 URL 的路径部分的确切格式匹配:

routeMatcher = new RegExp("^" + i.replace(/:[^\s\/]+/g, '([\\w-]+)') + "$");

如果您正在从路径window.location.pathname进行匹配,那么它可能没问题。

于 2012-12-19T10:29:44.740 回答