Backbone.js扩展与继承 #
一、extend方法 #
1.1 基本用法 #
javascript
var User = Backbone.Model.extend({
defaults: {
name: '',
email: ''
},
initialize: function() {
console.log('User created');
}
});
1.2 extend原理 #
javascript
var extend = function(protoProps, staticProps) {
var parent = this;
var child;
if (protoProps && _.has(protoProps, 'constructor')) {
child = protoProps.constructor;
} else {
child = function() { return parent.apply(this, arguments); };
}
_.extend(child, parent, staticProps);
var Surrogate = function() { this.constructor = child; };
Surrogate.prototype = parent.prototype;
child.prototype = new Surrogate;
if (protoProps) _.extend(child.prototype, protoProps);
child.__super__ = parent.prototype;
return child;
};
1.3 实例属性与类属性 #
javascript
var User = Backbone.Model.extend({
defaults: {
name: ''
}
}, {
findByName: function(name) {
return new this({ name: name });
}
});
var user = User.findByName('张三');
二、继承模式 #
2.1 基本继承 #
javascript
var Animal = Backbone.Model.extend({
defaults: {
name: '',
age: 0
},
speak: function() {
console.log(this.get('name') + ' makes a sound');
}
});
var Dog = Animal.extend({
speak: function() {
console.log(this.get('name') + ' barks');
}
});
var dog = new Dog({ name: 'Buddy' });
dog.speak();
2.2 调用父类方法 #
javascript
var Animal = Backbone.Model.extend({
initialize: function() {
console.log('Animal initialized');
}
});
var Dog = Animal.extend({
initialize: function() {
Animal.prototype.initialize.apply(this, arguments);
console.log('Dog initialized');
}
});
var dog = new Dog();
2.3 使用__super__ #
javascript
var Animal = Backbone.Model.extend({
speak: function() {
return 'sound';
}
});
var Dog = Animal.extend({
speak: function() {
return Dog.__super__.speak.call(this) + ' - bark';
}
});
var dog = new Dog();
console.log(dog.speak());
2.4 多层继承 #
javascript
var Base = Backbone.Model.extend({
initialize: function() {
console.log('Base');
}
});
var Middle = Base.extend({
initialize: function() {
Middle.__super__.initialize.apply(this, arguments);
console.log('Middle');
}
});
var Child = Middle.extend({
initialize: function() {
Child.__super__.initialize.apply(this, arguments);
console.log('Child');
}
});
var child = new Child();
三、混入模式 #
3.1 基本混入 #
javascript
var TimestampMixin = {
getTimestamp: function() {
return new Date().toISOString();
},
setCreatedAt: function() {
this.set('createdAt', this.getTimestamp());
}
};
var User = Backbone.Model.extend({
initialize: function() {
this.setCreatedAt();
}
});
_.extend(User.prototype, TimestampMixin);
3.2 多个混入 #
javascript
var TimestampMixin = {
touch: function() {
this.set('updatedAt', new Date().toISOString());
}
};
var ValidationMixin = {
validateRequired: function(fields) {
var errors = [];
fields.forEach(function(field) {
if (!this.get(field)) {
errors.push(field + ' is required');
}
}, this);
return errors.length > 0 ? errors : undefined;
}
};
var User = Backbone.Model.extend({
validate: function(attrs) {
return this.validateRequired(['name', 'email']);
}
});
_.extend(User.prototype, TimestampMixin, ValidationMixin);
3.3 混入函数 #
javascript
function mixin(target) {
var sources = Array.prototype.slice.call(arguments, 1);
sources.forEach(function(source) {
Object.keys(source).forEach(function(key) {
target[key] = source[key];
});
});
return target;
}
var User = Backbone.Model.extend({});
mixin(User.prototype, TimestampMixin, ValidationMixin);
四、自定义扩展 #
4.1 基类扩展 #
javascript
var BaseModel = Backbone.Model.extend({
initialize: function(attrs, options) {
this.options = options || {};
this.on('change', this.onChange, this);
},
onChange: function() {
console.log('Model changed');
},
fetch: function(options) {
options = options || {};
options.data = _.extend(options.data || {}, {
timestamp: Date.now()
});
return Backbone.Model.prototype.fetch.call(this, options);
}
});
var User = BaseModel.extend({
defaults: {
name: ''
}
});
4.2 视图基类 #
javascript
var BaseView = Backbone.View.extend({
initialize: function(options) {
this.options = options || {};
this.childViews = [];
},
render: function() {
this.$el.html(this.template(this.getTemplateData()));
this.afterRender();
return this;
},
getTemplateData: function() {
if (this.model) {
return this.model.toJSON();
}
if (this.collection) {
return { items: this.collection.toJSON() };
}
return {};
},
afterRender: function() {},
addChild: function(view) {
this.childViews.push(view);
return view;
},
remove: function() {
this.childViews.forEach(function(view) {
view.remove();
});
this.childViews = [];
Backbone.View.prototype.remove.call(this);
}
});
4.3 集合基类 #
javascript
var BaseCollection = Backbone.Collection.extend({
initialize: function(models, options) {
this.options = options || {};
},
fetch: function(options) {
options = options || {};
this.trigger('fetch:start');
var success = options.success;
var error = options.error;
var self = this;
options.success = function() {
self.trigger('fetch:success');
if (success) success.apply(this, arguments);
};
options.error = function() {
self.trigger('fetch:error');
if (error) error.apply(this, arguments);
};
return Backbone.Collection.prototype.fetch.call(this, options);
}
});
五、实用示例 #
5.1 可复用组件 #
javascript
var SelectableView = BaseView.extend({
events: {
'click': 'toggleSelect'
},
initialize: function(options) {
BaseView.prototype.initialize.call(this, options);
this.selected = false;
},
toggleSelect: function(e) {
e.stopPropagation();
this.selected = !this.selected;
this.$el.toggleClass('selected', this.selected);
this.trigger('select:toggle', this.selected);
},
select: function() {
this.selected = true;
this.$el.addClass('selected');
this.trigger('select', true);
},
deselect: function() {
this.selected = false;
this.$el.removeClass('selected');
this.trigger('select', false);
}
});
5.2 状态管理 #
javascript
var StatefulModel = Backbone.Model.extend({
initialize: function() {
this.state = 'idle';
this.previousState = null;
},
setState: function(newState) {
this.previousState = this.state;
this.state = newState;
this.trigger('state:change', newState, this.previousState);
this.trigger('state:' + newState);
},
getState: function() {
return this.state;
},
isState: function(state) {
return this.state === state;
}
});
5.3 插件系统 #
javascript
var PluginSystem = {
plugins: [],
use: function(plugin, options) {
this.plugins.push({
plugin: plugin,
options: options || {}
});
if (plugin.install) {
plugin.install(this, options);
}
},
initializePlugins: function() {
this.plugins.forEach(function(item) {
if (item.plugin.initialize) {
item.plugin.initialize(this, item.options);
}
}, this);
}
};
var AppModel = Backbone.Model.extend({
initialize: function() {
_.extend(this, PluginSystem);
this.initializePlugins();
}
});
六、总结 #
6.1 扩展方法 #
| 方法 | 说明 |
|---|---|
| extend(protoProps, staticProps) | 创建子类 |
| super | 访问父类原型 |
| _.extend | 混入属性 |
6.2 最佳实践 #
- 使用基类封装通用逻辑
- 合理使用继承层次
- 使用混入实现代码复用
- 调用父类方法时保持上下文
- 避免过深的继承层次
最后更新:2026-03-28