Backbone.js模型属性 #
一、属性基础 #
1.1 属性存储 #
Backbone.js模型的属性存储在 attributes 对象中:
javascript
var user = new Backbone.Model({ name: '张三', age: 25 });
console.log(user.attributes);
1.2 属性访问原则 #
text
推荐方式:使用 get/set 方法
├── 触发事件
├── 支持验证
├── 支持计算属性
└── 保持封装性
不推荐:直接访问 attributes
├── 不触发事件
├── 绕过验证
└── 破坏封装性
二、获取属性 #
2.1 get方法 #
javascript
var user = new Backbone.Model({
name: '张三',
age: 25,
email: 'zhangsan@example.com'
});
var name = user.get('name');
var age = user.get('age');
console.log(name);
console.log(age);
2.2 获取嵌套属性 #
javascript
var user = new Backbone.Model({
name: '张三',
address: {
city: '北京',
district: '朝阳'
}
});
var address = user.get('address');
console.log(address.city);
2.3 toJSON方法 #
javascript
var user = new Backbone.Model({
name: '张三',
age: 25
});
var json = user.toJSON();
console.log(json);
console.log(JSON.stringify(user));
2.4 获取属性列表 #
javascript
var user = new Backbone.Model({
name: '张三',
age: 25,
email: 'zhangsan@example.com'
});
var keys = Object.keys(user.attributes);
console.log(keys);
三、设置属性 #
3.1 设置单个属性 #
javascript
var user = new Backbone.Model();
user.set('name', '张三');
user.set('age', 25);
console.log(user.toJSON());
3.2 设置多个属性 #
javascript
var user = new Backbone.Model();
user.set({
name: '李四',
age: 30,
email: 'lisi@example.com'
});
console.log(user.toJSON());
3.3 链式设置 #
javascript
var user = new Backbone.Model();
user.set('name', '张三')
.set('age', 25)
.set('email', 'zhangsan@example.com');
console.log(user.toJSON());
3.4 set方法选项 #
javascript
var user = new Backbone.Model({ name: '张三' });
user.on('change', function() {
console.log('属性已变化');
});
user.set('name', '李四', {
silent: false,
validate: true
});
选项详解:
| 选项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| silent | Boolean | false | 是否静默设置(不触发事件) |
| validate | Boolean | true | 是否调用验证函数 |
| unset | Boolean | false | 是否删除属性 |
3.5 静默设置 #
javascript
var user = new Backbone.Model({ name: '张三' });
user.on('change', function() {
console.log('触发了change事件');
});
user.set('name', '李四', { silent: true });
console.log(user.get('name'));
四、删除属性 #
4.1 unset方法 #
javascript
var user = new Backbone.Model({
name: '张三',
age: 25,
email: 'zhangsan@example.com'
});
user.unset('email');
console.log(user.has('email'));
console.log(user.toJSON());
4.2 clear方法 #
javascript
var user = new Backbone.Model({
name: '张三',
age: 25
});
user.clear();
console.log(user.toJSON());
4.3 使用set删除 #
javascript
var user = new Backbone.Model({
name: '张三',
age: 25
});
user.set('age', null, { unset: true });
console.log(user.has('age'));
4.4 删除触发事件 #
javascript
var user = new Backbone.Model({ name: '张三' });
user.on('change:name', function(model, value) {
console.log('name属性已删除');
});
user.unset('name');
五、检查属性 #
5.1 has方法 #
javascript
var user = new Backbone.Model({
name: '张三',
age: 0,
email: ''
});
console.log(user.has('name'));
console.log(user.has('age'));
console.log(user.has('email'));
console.log(user.has('phone'));
5.2 检查非空属性 #
javascript
var user = new Backbone.Model({
name: '张三',
age: 0,
email: ''
});
function hasValue(model, attr) {
var value = model.get(attr);
return value !== null && value !== undefined && value !== '';
}
console.log(hasValue(user, 'name'));
console.log(hasValue(user, 'age'));
console.log(hasValue(user, 'email'));
5.3 检查属性类型 #
javascript
var user = new Backbone.Model({
name: '张三',
age: 25,
tags: ['js', 'backbone'],
active: true
});
console.log(typeof user.get('name'));
console.log(typeof user.get('age'));
console.log(Array.isArray(user.get('tags')));
console.log(typeof user.get('active'));
六、属性转义 #
6.1 escape方法 #
javascript
var user = new Backbone.Model({
name: '<script>alert("XSS")</script>',
bio: '<p>这是<b>简介</b></p>'
});
var safeName = user.escape('name');
var safeBio = user.escape('bio');
console.log(safeName);
console.log(safeBio);
6.2 安全渲染 #
javascript
var UserView = Backbone.View.extend({
template: _.template(
'<div class="user">' +
' <h2><%= name %></h2>' +
' <p><%= bio %></p>' +
'</div>'
),
render: function() {
var data = {
name: this.model.escape('name'),
bio: this.model.escape('bio')
};
this.$el.html(this.template(data));
return this;
}
});
七、属性变化追踪 #
7.1 previous方法 #
javascript
var user = new Backbone.Model({ name: '张三', age: 25 });
user.on('change:name', function(model, value) {
var oldValue = model.previous('name');
console.log('旧值:', oldValue);
console.log('新值:', value);
});
user.set('name', '李四');
7.2 previousAttributes方法 #
javascript
var user = new Backbone.Model({ name: '张三', age: 25 });
user.on('change', function(model) {
var oldAttrs = model.previousAttributes();
var newAttrs = model.toJSON();
console.log('变化前:', oldAttrs);
console.log('变化后:', newAttrs);
});
user.set({ name: '李四', age: 30 });
7.3 changedAttributes方法 #
javascript
var user = new Backbone.Model({ name: '张三', age: 25 });
user.on('change', function(model) {
var changed = model.changedAttributes();
console.log('变化的属性:', changed);
});
user.set({ name: '李四', age: 25 });
7.4 hasChanged方法 #
javascript
var user = new Backbone.Model({ name: '张三', age: 25 });
user.on('change', function(model) {
if (model.hasChanged('name')) {
console.log('name已变化');
}
if (model.hasChanged('age')) {
console.log('age已变化');
}
});
user.set({ name: '李四' });
八、属性事件 #
8.1 change事件 #
javascript
var user = new Backbone.Model();
user.on('change', function(model, options) {
console.log('模型已变化');
});
user.set('name', '张三');
8.2 change:attr事件 #
javascript
var user = new Backbone.Model();
user.on('change:name', function(model, value, options) {
console.log('name变化为:', value);
});
user.on('change:age', function(model, value, options) {
console.log('age变化为:', value);
});
user.set({ name: '张三', age: 25 });
8.3 批量监听 #
javascript
var user = new Backbone.Model();
user.on({
'change:name': function(model, value) {
console.log('name:', value);
},
'change:age': function(model, value) {
console.log('age:', value);
},
'change:email': function(model, value) {
console.log('email:', value);
}
});
user.set({
name: '张三',
age: 25,
email: 'zhangsan@example.com'
});
8.4 事件上下文 #
javascript
var UserView = Backbone.View.extend({
initialize: function() {
this.listenTo(this.model, 'change', this.render);
this.listenTo(this.model, 'change:name', this.onNameChange);
},
render: function() {
console.log('重新渲染');
return this;
},
onNameChange: function(model, value) {
console.log('姓名变化:', value);
}
});
九、默认值处理 #
9.1 defaults对象 #
javascript
var User = Backbone.Model.extend({
defaults: {
name: '匿名用户',
age: 0,
email: '',
role: 'user'
}
});
var user = new User();
console.log(user.toJSON());
9.2 defaults函数 #
javascript
var Todo = Backbone.Model.extend({
defaults: function() {
return {
title: '未命名任务',
completed: false,
createdAt: new Date().toISOString(),
priority: 'normal'
};
}
});
var todo = new Todo();
console.log(todo.toJSON());
9.3 默认值合并 #
javascript
var User = Backbone.Model.extend({
defaults: {
name: '匿名',
age: 0,
role: 'user'
}
});
var user = new User({ name: '张三' });
console.log(user.toJSON());
9.4 深层默认值 #
javascript
var User = Backbone.Model.extend({
defaults: function() {
return {
name: '',
settings: {
theme: 'light',
language: 'zh-CN',
notifications: true
}
};
}
});
var user1 = new User();
var user2 = new User();
user1.get('settings').theme = 'dark';
console.log(user1.get('settings').theme);
console.log(user2.get('settings').theme);
十、实用技巧 #
10.1 属性类型转换 #
javascript
var Product = Backbone.Model.extend({
defaults: {
price: 0,
quantity: 1,
active: false
},
set: function(key, value, options) {
if (typeof key === 'object') {
options = value;
value = key;
key = null;
}
var attrs = key || value;
if (attrs.price !== undefined) {
attrs.price = parseFloat(attrs.price) || 0;
}
if (attrs.quantity !== undefined) {
attrs.quantity = parseInt(attrs.quantity, 10) || 0;
}
if (attrs.active !== undefined) {
attrs.active = Boolean(attrs.active);
}
return Backbone.Model.prototype.set.call(this, attrs, options);
}
});
var product = new Product({ price: '99.99', quantity: '5', active: 'true' });
console.log(product.toJSON());
10.2 计算属性 #
javascript
var Rectangle = Backbone.Model.extend({
defaults: {
width: 0,
height: 0
},
getArea: function() {
return this.get('width') * this.get('height');
},
getPerimeter: function() {
return 2 * (this.get('width') + this.get('height'));
},
isSquare: function() {
return this.get('width') === this.get('height');
}
});
var rect = new Rectangle({ width: 10, height: 5 });
console.log('面积:', rect.getArea());
console.log('周长:', rect.getPerimeter());
console.log('是否正方形:', rect.isSquare());
10.3 属性别名 #
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('李 四');
10.4 属性观察者 #
javascript
var User = Backbone.Model.extend({
initialize: function() {
this.on('change:email', this.validateEmail, this);
},
validateEmail: function(model, email) {
if (email && !email.match(/^[\w-]+@[\w-]+\.[a-z]+$/i)) {
console.warn('邮箱格式可能不正确:', email);
}
}
});
var user = new User();
user.set('email', 'invalid-email');
user.set('email', 'valid@example.com');
十一、总结 #
11.1 属性操作API #
| 方法 | 说明 | 返回值 |
|---|---|---|
| get(attr) | 获取属性值 | 属性值 |
| set(key, value, options) | 设置属性值 | this |
| unset(attr, options) | 删除属性 | this |
| clear(options) | 删除所有属性 | this |
| has(attr) | 检查属性是否存在 | Boolean |
| escape(attr) | 获取转义后的属性值 | String |
| toJSON() | 获取属性副本 | Object |
11.2 变化追踪API #
| 方法 | 说明 | 返回值 |
|---|---|---|
| previous(attr) | 获取变化前的属性值 | 属性值 |
| previousAttributes() | 获取变化前的所有属性 | Object |
| changedAttributes(diff) | 获取变化的属性 | Object |
| hasChanged(attr) | 检查属性是否变化 | Boolean |
11.3 最佳实践 #
- 始终使用
get/set方法访问属性 - 使用
escape处理用户输入 - 使用函数形式的
defaults避免引用共享 - 合理使用事件监听属性变化
- 将计算属性封装为模型方法
最后更新:2026-03-28