Backbone.js历史管理 #
一、History概述 #
1.1 什么是History #
Backbone.history 是全局路由器,用于监听URL变化并触发相应的路由处理。
text
History职责
├── 监听URL变化
├── 管理浏览器历史记录
├── 匹配路由规则
└── 触发路由处理函数
1.2 两种模式 #
| 模式 | URL格式 | 特点 |
|---|---|---|
| hash | #/users | 兼容性好,不需要服务器配置 |
| pushState | /users | URL美观,需要服务器配置 |
二、启动History #
2.1 基本启动 #
javascript
var router = new AppRouter();
Backbone.history.start();
2.2 start选项 #
javascript
Backbone.history.start({
pushState: true,
hashChange: true,
root: '/app/',
silent: false
});
| 选项 | 默认值 | 说明 |
|---|---|---|
| pushState | false | 使用HTML5 History API |
| hashChange | true | 监听hash变化 |
| root | ‘/’ | 应用根路径 |
| silent | false | 是否静默启动 |
2.3 启动时机 #
javascript
$(function() {
var router = new AppRouter();
Backbone.history.start();
});
2.4 检查启动状态 #
javascript
if (!Backbone.History.started) {
Backbone.history.start();
}
三、pushState模式 #
3.1 启用pushState #
javascript
Backbone.history.start({
pushState: true,
root: '/myapp/'
});
3.2 URL格式 #
text
Hash模式: http://example.com/#/users/1
pushState模式: http://example.com/users/1
3.3 服务器配置 #
服务器需要配置将所有请求重定向到入口页面:
Nginx配置:
nginx
location / {
try_files $uri $uri/ /index.html;
}
Apache配置:
apache
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.html$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.html [L]
</IfModule>
Node.js Express配置:
javascript
app.get('*', function(req, res) {
res.sendFile(path.join(__dirname, 'index.html'));
});
3.4 处理链接 #
javascript
$(document).on('click', 'a[href^="/"]', function(e) {
var href = $(this).attr('href');
var root = Backbone.history.root;
if (href.indexOf(root) === 0) {
e.preventDefault();
Backbone.history.navigate(href.replace(root, ''), { trigger: true });
}
});
3.5 兼容性检测 #
javascript
if (Backbone.history.supportsPushState()) {
Backbone.history.start({ pushState: true });
} else {
Backbone.history.start();
}
四、hash模式 #
4.1 默认模式 #
javascript
Backbone.history.start();
4.2 URL格式 #
text
http://example.com/#/users
http://example.com/#/users/1
http://example.com/#/posts/2024/03
4.3 hashChange事件 #
javascript
$(window).on('hashchange', function() {
console.log('Hash changed:', window.location.hash);
});
4.4 优点 #
- 不需要服务器配置
- 兼容所有浏览器
- 部署简单
4.5 缺点 #
- URL不够美观
- 不利于SEO
- 无法使用锚点
五、History API #
5.1 navigate方法 #
javascript
Backbone.history.navigate('users', { trigger: true });
Backbone.history.navigate('users/1', { trigger: true, replace: true });
5.2 loadUrl方法 #
javascript
var matched = Backbone.history.loadUrl();
console.log('是否匹配路由:', matched);
5.3 getFragment方法 #
javascript
var fragment = Backbone.history.getFragment();
console.log('当前路由:', fragment);
5.4 解析URL #
javascript
var fragment = Backbone.history.getFragment('/users/1?tab=profile');
console.log(fragment);
六、历史记录操作 #
6.1 原生History API #
javascript
window.history.length;
window.history.back();
window.history.forward();
window.history.go(-2);
window.history.pushState({ page: 1 }, 'Title', '/page1');
window.history.replaceState({ page: 2 }, 'Title', '/page2');
6.2 popstate事件 #
javascript
$(window).on('popstate', function(e) {
console.log('状态:', e.originalEvent.state);
});
6.3 状态管理 #
javascript
var AppRouter = Backbone.Router.extend({
navigate: function(fragment, options) {
options = options || {};
var state = {
route: fragment,
timestamp: Date.now()
};
if (options.replace) {
window.history.replaceState(state, '', '#' + fragment);
} else {
window.history.pushState(state, '', '#' + fragment);
}
if (options.trigger) {
this.loadUrl(fragment);
}
return this;
}
});
七、实用示例 #
7.1 历史管理器 #
javascript
var HistoryManager = {
maxLength: 50,
history: [],
init: function() {
var self = this;
Backbone.history.on('route', function(router, name) {
self.add({
route: Backbone.history.getFragment(),
name: name,
timestamp: Date.now()
});
});
},
add: function(item) {
this.history.push(item);
if (this.history.length > this.maxLength) {
this.history.shift();
}
},
getLast: function() {
return this.history[this.history.length - 1];
},
getPrevious: function() {
return this.history[this.history.length - 2];
},
canGoBack: function() {
return this.history.length > 1;
}
};
7.2 路由恢复 #
javascript
var RouteRecovery = {
storageKey: 'lastRoute',
save: function() {
var fragment = Backbone.history.getFragment();
localStorage.setItem(this.storageKey, fragment);
},
restore: function() {
var fragment = localStorage.getItem(this.storageKey);
if (fragment) {
Backbone.history.navigate(fragment, { trigger: true });
}
},
clear: function() {
localStorage.removeItem(this.storageKey);
}
};
$(window).on('beforeunload', function() {
RouteRecovery.save();
});
$(function() {
var router = new AppRouter();
Backbone.history.start();
RouteRecovery.restore();
});
7.3 页面状态保存 #
javascript
var PageState = {
states: {},
save: function(key, state) {
this.states[key] = {
state: state,
route: Backbone.history.getFragment(),
timestamp: Date.now()
};
},
get: function(key) {
return this.states[key];
},
restore: function(key) {
var saved = this.states[key];
if (saved) {
return saved.state;
}
return null;
},
clear: function(key) {
if (key) {
delete this.states[key];
} else {
this.states = {};
}
}
};
var UserListView = Backbone.View.extend({
initialize: function() {
var saved = PageState.restore('userList');
if (saved) {
this.page = saved.page;
this.filter = saved.filter;
}
},
saveState: function() {
PageState.save('userList', {
page: this.page,
filter: this.filter
});
}
});
7.4 智能后退 #
javascript
var SmartBack = {
defaultRoute: '',
excludedRoutes: ['login', 'register'],
init: function(defaultRoute) {
this.defaultRoute = defaultRoute || '';
},
goBack: function() {
var current = Backbone.history.getFragment();
if (this.excludedRoutes.indexOf(current) !== -1) {
Backbone.history.navigate(this.defaultRoute, { trigger: true });
return;
}
if (window.history.length > 1) {
window.history.back();
} else {
Backbone.history.navigate(this.defaultRoute, { trigger: true });
}
}
};
SmartBack.init('dashboard');
$('.btn-back').on('click', function() {
SmartBack.goBack();
});
八、总结 #
8.1 History方法 #
| 方法 | 说明 |
|---|---|
| start(options) | 启动历史管理 |
| navigate(fragment, options) | 导航到指定路由 |
| loadUrl(fragment) | 加载URL |
| getFragment() | 获取当前路由片段 |
8.2 模式对比 #
| 特性 | hash模式 | pushState模式 |
|---|---|---|
| URL美观 | 否 | 是 |
| 服务器配置 | 不需要 | 需要 |
| SEO友好 | 否 | 是 |
| 兼容性 | 好 | 较好 |
8.3 最佳实践 #
- 根据需求选择合适的模式
- pushState模式需要服务器配置
- 保存页面状态提升用户体验
- 处理浏览器前进后退
- 实现智能后退逻辑
最后更新:2026-03-28