出于多种原因,包括搜索引擎蜘蛛和链接共享;您的网站应该可以在没有 History API 的情况下运行。如果用户看到http://example.org/poodles/red并想向其他人展示您网站上的红色贵宾犬,他们会复制该链接。其他访问者需要能够在相同的 URL 上看到相同的内容;即使他们不是从主页开始。
出于这个原因,我建议使用 History API 作为渐进式增强。在可用的地方,您应该使用它来提供更好的用户体验。在不可用的地方,链接应该正常运行。
这是一个示例路由器(如 Sammy),如果 history.pushState 不可用,它只允许默认浏览器导航。
关于淘汰赛部分;我在一个 KnockoutJS 项目中使用了它,它运行良好。
(function($){
function Route(path, callback) {
function escapeRegExp(str) {
return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
}
// replace "/:something" with a regular expression fragment
var expression = escapeRegExp(path).replace(/\/:(\w+)+/g, "/(\\w+)*");
this.regex = new RegExp(expression);
this.callback = callback;
}
Route.prototype.test = function (path) {
this.regex.lastIndex = 0;
var match = this.regex.exec(path);
if (match !== null && match[0].length === path.length) {
// call it, passing any matching groups
this.callback.apply(this, match.slice(1));
return false;
}
};
function Router(paths) {
var self = this;
self.routes = [];
$.each(paths, function (path, callback) {
self.routes.push(new Route(path, callback));
});
self.listen();
self.doCallbacks(location.pathname);
}
Router.prototype.listen = function () {
var self = this, $document = $(document);
// watch for clicks on links
// does AJAX when ctrl is not down
// nor the href ends in .html
// nor the href is blank
// nor the href is /
$document.ready(function(e){
$document.on("click", "[href]", function(e){
var href = this.getAttribute("href");
if ( !e.ctrlKey && (href.indexOf(".html") !== href.length - 5) && (href.indexOf(".zip") !== href.length - 4) && href.length > 0 && href !== "/") {
e.preventDefault();
self.navigate(href);
}
});
});
window.addEventListener("popstate", function(e) {
self.doCallbacks(location.pathname);
});
};
Router.prototype.navigate = function(url) {
if (window.history && window.history.pushState) {
history.pushState(null, null, url);
this.doCallbacks(location.pathname);
}
};
Router.prototype.doCallbacks = function(url) {
var routes = this.routes;
for (var i=0; i<routes.length; i++){
var route = routes[i];
// it returns false when there's a match
if (route.test(url) === false) {
console.log("nav matched " + route.regex);
return;
}
}
if (typeof this.fourOhFour === "function") {
this.fourOhFour(url);
} else {
console.log("404 at ", url);
}
};
window.Router = Router;
}).call(this, jQuery);
示例用法:
router = new Router({
"/": function () {
},
"/category/:which": function (category) {
},
"/search/:query": function(query) {
},
"/search/:category/:query": function(category, query) {
},
"/:foo/:bar": function(foo, bar) {
}
});
router.fourOhFour = function(requestURL){
};