我想实现一个基于 Ajax 的哈希键导航,如下所示:
http://www.foo.bar/#/about/
http://www.foo.bar/#/news/
http://www.foo.bar/#/products/
如何实现这个结构?
使用基于哈希的导航结构,您将通过浏览器中的 JS 定义路线及其处理程序...当哈希更改时,会触发“hashchange”事件,并且“window.onhashchange”处理程序函数被称为。*
例如
if ("onhashchange" in window) {
alert("The browser supports the hashchange event!");
}
function locationHashChanged() {
if (location.hash === "#somecoolfeature") {
somecoolfeature();
}
}
window.onhashchange = locationHashChanged;
也可以选择使用最近引入的 HTML5 Pushstate。
查看 http://www.microjs.com/#spa 了解一些优秀的 JS 路由库 - 其中一些提供对 HTML5 Pushstate 的支持以及对旧版浏览器的 hashchange 的回退。
如果您想构建一个严肃的应用程序,您可以使用 Backbone.js 之类的东西来处理模型、视图、路由等。您还应该查看 Crossroads.js(路由库)及其随附的 Hasher.js (hashchange/ Pushstate 库)如果您不需要 Backbone 附带的所有额外功能。
...或者有 LeviRoutes(仅限 HTML5 Pushstate,非常类似于 Express for Node.js 中的路由)。
...或 Jquery BBQ(基于 Jquery/hashchange/一些不错的功能 - (github.com/cowboy/jquery-bbq)
...然后是 Director(hashchange/大量功能/在 Node.js 和浏览器中工作/类似于 Express 路由/主要由 Nodejitsu 的人员开发)。
*注意:如果您专注于 SEO,那么 hashchange/ajax 会引入一些问题...您可能需要阅读 Google 的网站管理员指南 -- http://code.google.com/web/ajaxcrawling/docs /getting-started.html
**附注您可以在 MicroJS.com 网站上找到上述所有库,除了 Jquery BBQ
使用上面给出的示例,并保持简单,您可以执行以下操作:
function aboutHandler() {
//Do stuff--e.g. get via AJAX -> render template (optional) -> append HTML to an element
}
function newsHandler() {
//Do stuff
}
function productsHandler() {
//Do stuff
}
function locationHashChanged() {
(location.hash === "#/about/") && aboutHandler();
(location.hash === "#/news/") && newsHandler();
(location.hash === "#/products/") && productsHandler();
}
}
window.onhashchange = locationHashChanged;
看起来您正在开发一个单页应用程序。所以,我建议您使用Backbone.js。这是您的任务的代码片段。
<script>
var Controller = Backbone.Router.extend({
routes: {
"/about/": "about",
"/news/": "news",
"/products/": "products"
},
about: function(){
// ...
},
news: function(){
// ...
},
products: functions(){
// ...
}
});
var controller = new Controller();
Backbone.history.start();
</script>
这是我的实现
function route_guide(path_array, routes) {
const descendant = path_array.shift();
if (descendant && routes.children?.[descendant]?.callback) {
route_guide(path_array, routes.children[descendant])
} else {
routes.callback([descendant ?? '', ...path_array]);
}
}
function hash_change_handler(hash) {
if (typeof ROUTES != 'object') {
return;
}
hash = hash.replace('#', '');
const hash_array = hash.split('/').filter(x => x.trim());
route_guide(hash_array, ROUTES);
}
window.onhashchange = function(e) {
e && e.preventDefault();
hash_change_handler(location.hash);
}
let ROUTES;
document.addEventListener('DOMContentLoaded', () => {
ROUTES = {
callback: () => {
// #/
},
children: {
chat: {
callback: (path_array) => {
// #/careers
}
children: {
callback: () => {
// #/careers/apply
}
}
}
}
}
})