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を入力すると、対応する関数名が返されます(文字列を関数として呼び出す方法を理解する必要があります)。問題は、私の例のように非常によく似た2つのルートがある場合、正規表現が両方に一致することです。上記の例では、理想的には2番目のルートのみを一致させたいのですが、もちろん最初のルートも一致するため、残念ながら両方が一致します。

正規表現が完全一致のみを返すようにする方法はありますか?入力URLのスラッシュをカウントし、スラッシュの数が一致するルートのみを呼び出すという別の解決策がありますが、これはかなりエレガントではないようです。

4

3 に答える 3

4

これを試して:

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

/末尾もカバーするようにサポートしたい場合は/users/1024/pictures/456/、次のように正規表現を変更できます。

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

これがあなたが必要としているものであるかどうかは完全にはわかりません。

とを使用^$て、正規表現をURLのパス部分の正確な形式と一致させます。

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

マッチングを行うためのパスを使用している場合window.location.pathnameは、おそらく問題ありません。

于 2012-12-19T10:29:44.740 に答える
2

正規表現をキャッシュするバリアントは次のとおりです(正規表現の'^''$'に注意してください)。

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 に答える