Backbone.js模型基础 #
一、什么是Model #
Model(模型)是Backbone.js的核心组件之一,用于管理应用程序的数据和业务逻辑。
1.1 Model的作用 #
text
Model职责
├── 数据存储:存储和管理应用数据
├── 数据验证:验证数据的有效性
├── 数据同步:与服务器进行数据同步
├── 业务逻辑:处理数据相关的业务逻辑
└── 事件通知:数据变化时通知相关组件
1.2 Model的特点 #
| 特点 | 说明 |
|---|---|
| 属性管理 | 通过get/set方法管理属性 |
| 事件驱动 | 属性变化时触发事件 |
| 验证机制 | 内置数据验证支持 |
| RESTful | 自动与RESTful API交互 |
| 唯一标识 | 每个模型有唯一id |
二、创建Model #
2.1 基本创建方式 #
javascript
var Todo = Backbone.Model.extend({
defaults: {
title: '',
completed: false,
createdAt: null
}
});
var todo = new Todo();
console.log(todo.toJSON());
2.2 extend方法 #
Backbone.Model.extend 用于创建自定义模型类:
javascript
var User = Backbone.Model.extend({
defaults: {
name: '',
email: '',
age: 0
},
initialize: function() {
console.log('User模型已创建');
}
});
extend参数:
| 参数 | 类型 | 说明 |
|---|---|---|
| properties | Object | 实例属性和方法 |
| classProperties | Object | 类属性和静态方法 |
2.3 初始化时传入属性 #
javascript
var todo = new Todo({
title: '学习Backbone.js',
completed: false
});
console.log(todo.get('title'));
2.4 initialize方法 #
initialize 方法在模型创建时自动调用:
javascript
var User = Backbone.Model.extend({
initialize: function(attributes, options) {
console.log('初始化属性:', attributes);
console.log('初始化选项:', options);
this.on('change', function() {
console.log('模型属性已变化');
});
}
});
var user = new User({ name: '张三' }, { silent: true });
三、属性操作 #
3.1 获取属性 #
javascript
var user = new User({ name: '张三', age: 25 });
// 获取单个属性
var name = user.get('name');
console.log(name);
// 获取所有属性(副本)
var attrs = user.toJSON();
console.log(attrs);
// 获取属性值(直接访问,不推荐)
var name = user.attributes.name;
3.2 设置属性 #
javascript
var user = new User();
// 设置单个属性
user.set('name', '李四');
// 设置多个属性
user.set({
name: '王五',
age: 30,
email: 'wangwu@example.com'
});
// 设置属性并触发事件
user.set('name', '赵六', { silent: false });
// 静默设置(不触发事件)
user.set('name', '钱七', { silent: true });
3.3 set方法选项 #
javascript
user.set('name', '张三', {
silent: false, // 是否静默设置
validate: true, // 是否验证
unset: false // 是否删除属性
});
选项说明:
| 选项 | 默认值 | 说明 |
|---|---|---|
| silent | false | 是否静默设置(不触发事件) |
| validate | true | 是否调用validate验证 |
| unset | false | 是否删除属性 |
3.4 删除属性 #
javascript
var user = new User({ name: '张三', age: 25 });
// 删除单个属性
user.unset('age');
// 删除所有属性
user.clear();
// 静默删除
user.unset('name', { silent: true });
3.5 检查属性 #
javascript
var user = new User({ name: '张三' });
// 检查属性是否存在
if (user.has('name')) {
console.log('name属性存在');
}
// 检查属性是否为空
if (!user.has('email')) {
console.log('email属性不存在');
}
3.6 转义属性 #
javascript
var user = new User({ name: '<script>alert("XSS")</script>' });
// 安全获取(转义HTML)
var safeName = user.escape('name');
console.log(safeName);
四、默认值 #
4.1 设置默认值 #
javascript
var Todo = Backbone.Model.extend({
defaults: {
title: '未命名任务',
completed: false,
createdAt: null,
priority: 'normal'
}
});
var todo = new Todo();
console.log(todo.toJSON());
4.2 函数形式的默认值 #
javascript
var Todo = Backbone.Model.extend({
defaults: function() {
return {
title: '未命名任务',
completed: false,
createdAt: new Date().toISOString(),
priority: 'normal'
};
}
});
4.3 默认值与传入属性合并 #
javascript
var Todo = Backbone.Model.extend({
defaults: {
title: '默认标题',
completed: false,
priority: 'normal'
}
});
var todo = new Todo({ title: '自定义标题' });
console.log(todo.toJSON());
五、模型标识 #
5.1 id属性 #
javascript
var user = new User({ id: 1, name: '张三' });
console.log(user.id);
console.log(user.get('id'));
console.log(user.isNew());
5.2 idAttribute #
javascript
var User = Backbone.Model.extend({
idAttribute: '_id'
});
var user = new User({ _id: 123, name: '张三' });
console.log(user.id);
console.log(user.idAttribute);
5.3 cid #
cid 是客户端自动生成的唯一标识:
javascript
var user1 = new User();
var user2 = new User();
console.log(user1.cid);
console.log(user2.cid);
5.4 isNew方法 #
javascript
var user1 = new User();
console.log(user1.isNew());
var user2 = new User({ id: 1 });
console.log(user2.isNew());
六、模型克隆 #
6.1 clone方法 #
javascript
var user = new User({ id: 1, name: '张三' });
var cloned = user.clone();
console.log(cloned.toJSON());
console.log(cloned.id);
console.log(cloned.cid);
6.2 克隆特点 #
javascript
var user = new User({ id: 1, name: '张三' });
var cloned = user.clone();
cloned.set('name', '李四');
console.log(user.get('name'));
console.log(cloned.get('name'));
七、模型事件 #
7.1 change事件 #
javascript
var user = new User({ name: '张三' });
user.on('change', function(model, options) {
console.log('模型已变化');
});
user.on('change:name', function(model, value, options) {
console.log('name已变更为:', value);
});
user.set('name', '李四');
7.2 事件类型 #
| 事件 | 触发时机 |
|---|---|
| change | 任何属性变化时 |
| change:attr | 特定属性变化时 |
| destroy | 模型销毁时 |
| sync | 同步成功时 |
| error | 同步失败或验证失败时 |
| invalid | 验证失败时 |
| request | 开始请求时 |
7.3 previous方法 #
javascript
var user = new User({ name: '张三', age: 25 });
user.on('change:name', function(model, value) {
var previous = model.previous('name');
console.log('旧值:', previous);
console.log('新值:', value);
});
user.set('name', '李四');
7.4 previousAttributes方法 #
javascript
var user = new User({ name: '张三', age: 25 });
user.on('change', function(model) {
var previous = model.previousAttributes();
console.log('所有旧值:', previous);
console.log('当前值:', model.toJSON());
});
user.set({ name: '李四', age: 30 });
八、模型方法 #
8.1 自定义方法 #
javascript
var User = Backbone.Model.extend({
defaults: {
firstName: '',
lastName: ''
},
getFullName: function() {
return this.get('firstName') + ' ' + this.get('lastName');
},
setFullName: function(fullName) {
var parts = fullName.split(' ');
this.set({
firstName: parts[0],
lastName: parts[1]
});
}
});
var user = new User({ firstName: '张', lastName: '三' });
console.log(user.getFullName());
user.setFullName('李 四');
8.2 计算属性 #
javascript
var Product = Backbone.Model.extend({
defaults: {
price: 0,
quantity: 1,
discount: 0
},
getTotal: function() {
var price = this.get('price');
var quantity = this.get('quantity');
var discount = this.get('discount');
return price * quantity * (1 - discount / 100);
},
getFormattedPrice: function() {
return '¥' + this.get('price').toFixed(2);
}
});
var product = new Product({ price: 100, quantity: 2, discount: 10 });
console.log(product.getTotal());
console.log(product.getFormattedPrice());
九、URL配置 #
9.1 urlRoot #
javascript
var User = Backbone.Model.extend({
urlRoot: '/api/users'
});
var user = new User({ id: 1 });
console.log(user.url());
9.2 url方法 #
javascript
var User = Backbone.Model.extend({
urlRoot: '/api/users',
url: function() {
var base = this.urlRoot;
if (this.isNew()) {
return base;
}
return base + '/' + this.id + '.json';
}
});
9.3 集合中的URL #
javascript
var User = Backbone.Model.extend({});
var Users = Backbone.Collection.extend({
model: User,
url: '/api/users'
});
var users = new Users();
var user = new User({ id: 1 }, { collection: users });
console.log(user.url());
十、实用示例 #
10.1 Todo模型 #
javascript
var Todo = Backbone.Model.extend({
defaults: {
title: '',
completed: false,
createdAt: null
},
initialize: function() {
if (!this.get('createdAt')) {
this.set('createdAt', new Date().toISOString());
}
},
toggle: function() {
this.set('completed', !this.get('completed'));
},
isExpired: function() {
var created = new Date(this.get('createdAt'));
var now = new Date();
var days = (now - created) / (1000 * 60 * 60 * 24);
return days > 7;
}
});
var todo = new Todo({ title: '学习Backbone.js' });
todo.toggle();
console.log(todo.isExpired());
10.2 用户模型 #
javascript
var User = Backbone.Model.extend({
urlRoot: '/api/users',
defaults: {
name: '',
email: '',
role: 'user',
active: true
},
validate: function(attrs) {
var errors = [];
if (!attrs.name || attrs.name.trim() === '') {
errors.push('姓名不能为空');
}
if (!attrs.email || !attrs.email.match(/^[\w-]+@[\w-]+\.[a-z]+$/i)) {
errors.push('邮箱格式不正确');
}
if (errors.length > 0) {
return errors;
}
},
isAdmin: function() {
return this.get('role') === 'admin';
},
activate: function() {
this.set('active', true);
},
deactivate: function() {
this.set('active', false);
}
});
10.3 文章模型 #
javascript
var Article = Backbone.Model.extend({
urlRoot: '/api/articles',
defaults: {
title: '',
content: '',
author: '',
tags: [],
published: false,
createdAt: null,
updatedAt: null
},
initialize: function() {
this.on('change', this.updateTimestamp);
if (!this.get('createdAt')) {
this.set('createdAt', new Date().toISOString());
}
},
updateTimestamp: function() {
this.set('updatedAt', new Date().toISOString(), { silent: true });
},
publish: function() {
this.set('published', true);
return this.save();
},
unpublish: function() {
this.set('published', false);
return this.save();
},
addTag: function(tag) {
var tags = this.get('tags').slice();
if (tags.indexOf(tag) === -1) {
tags.push(tag);
this.set('tags', tags);
}
},
removeTag: function(tag) {
var tags = this.get('tags').slice();
var index = tags.indexOf(tag);
if (index > -1) {
tags.splice(index, 1);
this.set('tags', tags);
}
},
getExcerpt: function(length) {
length = length || 100;
var content = this.get('content') || '';
if (content.length <= length) {
return content;
}
return content.substring(0, length) + '...';
}
});
十一、总结 #
11.1 Model核心API #
| 方法 | 说明 |
|---|---|
| get(attr) | 获取属性值 |
| set(attr, value) | 设置属性值 |
| unset(attr) | 删除属性 |
| clear() | 删除所有属性 |
| has(attr) | 检查属性是否存在 |
| escape(attr) | 转义后的属性值 |
| toJSON() | 获取属性副本 |
| clone() | 克隆模型 |
| isNew() | 是否为新模型 |
11.2 最佳实践 #
- 使用
defaults设置合理的默认值 - 使用
get/set方法而非直接访问attributes - 使用
escape处理用户输入 - 合理使用事件监听
- 将业务逻辑封装在模型方法中
最后更新:2026-03-28