Backbone.js模型事件 #

一、事件概述 #

1.1 什么是事件 #

Backbone.js的事件系统是一个发布订阅模式的实现,允许对象之间进行松耦合的通信。

text
事件系统
├── 发布者:触发事件的对象
├── 订阅者:监听事件的对象
└── 事件:两者之间的通信桥梁

1.2 Model继承Events #

所有Backbone模型都继承了Events模块:

javascript
var user = new Backbone.Model();

user.on('change', function() {
    console.log('模型已变化');
});

user.set('name', '张三');

二、事件绑定 #

2.1 on方法 #

javascript
var user = new Backbone.Model();

user.on('change', function(model) {
    console.log('模型已变化');
});

user.set('name', '张三');

2.2 绑定多个事件 #

javascript
var user = new Backbone.Model();

user.on('change destroy sync', function(model) {
    console.log('事件触发');
});

2.3 事件映射 #

javascript
var user = new Backbone.Model();

user.on({
    'change': function() {
        console.log('change事件');
    },
    'destroy': function() {
        console.log('destroy事件');
    },
    'sync': function() {
        console.log('sync事件');
    }
});

2.4 绑定上下文 #

javascript
var UserView = Backbone.View.extend({
    initialize: function() {
        this.model.on('change', this.render, this);
    },
    
    render: function() {
        console.log(this);
        return this;
    }
});

2.5 listenTo方法 #

javascript
var UserView = Backbone.View.extend({
    initialize: function() {
        this.listenTo(this.model, 'change', this.render);
    },
    
    render: function() {
        return this;
    }
});

2.6 on vs listenTo #

方法 说明 内存管理
on 直接绑定 需手动解绑
listenTo 监听其他对象 视图销毁时自动解绑

三、模型事件类型 #

3.1 change事件 #

javascript
var user = new Backbone.Model();

user.on('change', function(model, options) {
    console.log('模型属性已变化');
    console.log('变化的属性:', model.changedAttributes());
});

user.set('name', '张三');

3.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 });

3.3 destroy事件 #

javascript
var user = new Backbone.Model({ id: 1 });

user.on('destroy', function(model, collection, options) {
    console.log('模型已销毁');
});

user.destroy();

3.4 sync事件 #

javascript
var User = Backbone.Model.extend({
    urlRoot: '/api/users'
});

var user = new User({ id: 1 });

user.on('sync', function(model, response, options) {
    console.log('同步成功');
    console.log('服务器响应:', response);
});

user.fetch();

3.5 request事件 #

javascript
var User = Backbone.Model.extend({
    urlRoot: '/api/users'
});

var user = new User({ id: 1 });

user.on('request', function(model, xhr, options) {
    console.log('请求已发送');
});

user.fetch();

3.6 error事件 #

javascript
var User = Backbone.Model.extend({
    urlRoot: '/api/users'
});

var user = new User({ id: 999 });

user.on('error', function(model, response, options) {
    console.log('请求失败');
    console.log('状态码:', response.status);
});

user.fetch();

3.7 invalid事件 #

javascript
var User = Backbone.Model.extend({
    validate: function(attrs) {
        if (!attrs.name) {
            return '姓名不能为空';
        }
    }
});

var user = new User();

user.on('invalid', function(model, error, options) {
    console.log('验证失败:', error);
});

user.set({ name: '' }, { validate: true });

四、事件触发 #

4.1 trigger方法 #

javascript
var user = new Backbone.Model();

user.on('custom:event', function(data) {
    console.log('自定义事件触发:', data);
});

user.trigger('custom:event', { message: 'Hello' });

4.2 传递参数 #

javascript
var user = new Backbone.Model();

user.on('notify', function(message, type) {
    console.log('[' + type + ']', message);
});

user.trigger('notify', '操作成功', 'success');
user.trigger('notify', '操作失败', 'error');

4.3 触发多个事件 #

javascript
var user = new Backbone.Model();

user.on('event1 event2 event3', function() {
    console.log('事件触发');
});

user.trigger('event1 event2');

五、事件解绑 #

5.1 off方法 #

javascript
var user = new Backbone.Model();

var handler = function() {
    console.log('事件触发');
};

user.on('change', handler);
user.off('change', handler);

5.2 解绑所有事件 #

javascript
var user = new Backbone.Model();

user.on('change', function() {});
user.on('destroy', function() {});

user.off();

5.3 解绑特定事件 #

javascript
var user = new Backbone.Model();

user.on('change', function() {});
user.on('destroy', function() {});

user.off('change');

5.4 解绑特定处理函数 #

javascript
var user = new Backbone.Model();

var handler1 = function() { console.log('handler1'); };
var handler2 = function() { console.log('handler2'); };

user.on('change', handler1);
user.on('change', handler2);

user.off('change', handler1);

5.5 stopListening方法 #

javascript
var view = new Backbone.View();
var model = new Backbone.Model();

view.listenTo(model, 'change', function() {
    console.log('模型变化');
});

view.stopListening(model);

5.6 解绑所有监听 #

javascript
var view = new Backbone.View();
var model1 = new Backbone.Model();
var model2 = new Backbone.Model();

view.listenTo(model1, 'change', function() {});
view.listenTo(model2, 'change', function() {});

view.stopListening();

六、一次性事件 #

6.1 once方法 #

javascript
var user = new Backbone.Model();

user.once('change', function() {
    console.log('只触发一次');
});

user.set('name', '张三');
user.set('name', '李四');

6.2 listenToOnce方法 #

javascript
var view = new Backbone.View();
var model = new Backbone.Model();

view.listenToOnce(model, 'change', function() {
    console.log('只触发一次');
});

model.set('name', '张三');
model.set('name', '李四');

七、事件对象 #

7.1 事件回调参数 #

javascript
var user = new Backbone.Model();

user.on('change', function(model, options) {
    console.log('模型:', model);
    console.log('选项:', options);
});

user.set('name', '张三', { silent: false });

7.2 change事件参数 #

javascript
var user = new Backbone.Model();

user.on('change:name', function(model, value, options) {
    console.log('模型:', model);
    console.log('新值:', value);
    console.log('选项:', options);
});

user.set('name', '张三');

7.3 sync事件参数 #

javascript
var User = Backbone.Model.extend({
    urlRoot: '/api/users'
});

var user = new User({ id: 1 });

user.on('sync', function(model, response, options) {
    console.log('模型:', model);
    console.log('响应:', response);
    console.log('选项:', options);
});

user.fetch();

八、事件高级用法 #

8.1 事件命名空间 #

javascript
var user = new Backbone.Model();

user.on('change:name', function() {
    console.log('name变化');
});

user.on('change:age', function() {
    console.log('age变化');
});

user.on('change', function() {
    console.log('任意属性变化');
});

8.2 事件冒泡 #

Collection会代理Model的事件:

javascript
var User = Backbone.Model.extend({});
var Users = Backbone.Collection.extend({
    model: User
});

var users = new Users();

users.on('change', function(model) {
    console.log('集合中的模型变化:', model.get('name'));
});

var user = new User({ name: '张三' });
users.add(user);

user.set('name', '李四');

8.3 事件队列 #

javascript
var user = new Backbone.Model();

user.on('change', function() {
    console.log('处理器1');
});

user.on('change', function() {
    console.log('处理器2');
});

user.on('change', function() {
    console.log('处理器3');
});

user.set('name', '张三');

8.4 条件事件 #

javascript
var User = Backbone.Model.extend({
    initialize: function() {
        this.on('change:status', function(model, status) {
            if (status === 'active') {
                this.trigger('activated');
            } else if (status === 'inactive') {
                this.trigger('deactivated');
            }
        });
    }
});

var user = new User();

user.on('activated', function() {
    console.log('用户已激活');
});

user.on('deactivated', function() {
    console.log('用户已停用');
});

user.set('status', 'active');

九、实用示例 #

9.1 状态管理 #

javascript
var Task = Backbone.Model.extend({
    defaults: {
        status: 'pending'
    },
    
    initialize: function() {
        this.on('change:status', this.onStatusChange);
    },
    
    onStatusChange: function(model, status) {
        var events = {
            'pending': 'pending',
            'in_progress': 'started',
            'completed': 'completed',
            'cancelled': 'cancelled'
        };
        
        this.trigger(events[status] || 'statusChange', this);
    },
    
    start: function() {
        this.set('status', 'in_progress');
    },
    
    complete: function() {
        this.set('status', 'completed');
    },
    
    cancel: function() {
        this.set('status', 'cancelled');
    }
});

var task = new Task();

task.on('started', function() {
    console.log('任务已开始');
});

task.on('completed', function() {
    console.log('任务已完成');
});

task.start();
task.complete();

9.2 自动保存 #

javascript
var Document = Backbone.Model.extend({
    urlRoot: '/api/documents',
    
    initialize: function() {
        this.on('change', this.autoSave, this);
    },
    
    autoSave: _.debounce(function() {
        if (!this.isNew() || this.hasContent()) {
            this.save();
        }
    }, 1000),
    
    hasContent: function() {
        return this.get('title') || this.get('content');
    }
});

9.3 属性联动 #

javascript
var User = Backbone.Model.extend({
    initialize: function() {
        this.on('change:firstName change:lastName', this.updateFullName);
        this.on('change:birthDate', this.updateAge);
    },
    
    updateFullName: function() {
        var fullName = (this.get('firstName') || '') + ' ' + (this.get('lastName') || '');
        this.set('fullName', fullName.trim(), { silent: true });
    },
    
    updateAge: function() {
        var birthDate = new Date(this.get('birthDate'));
        var now = new Date();
        var age = now.getFullYear() - birthDate.getFullYear();
        this.set('age', age, { silent: true });
    }
});

9.4 事件日志 #

javascript
var BaseModel = Backbone.Model.extend({
    initialize: function() {
        this.on('all', function(eventName) {
            console.log('[Event]', eventName, this.toJSON());
        });
    }
});

var User = BaseModel.extend({});

var user = new User();
user.set('name', '张三');

十、总结 #

10.1 事件方法 #

方法 说明
on(event, callback, context) 绑定事件
off(event, callback) 解绑事件
trigger(event, *args) 触发事件
once(event, callback, context) 绑定一次性事件
listenTo(obj, event, callback) 监听其他对象事件
stopListening(obj, event, callback) 停止监听
listenToOnce(obj, event, callback) 一次性监听

10.2 模型事件 #

事件 触发时机
change 属性变化时
change:attr 特定属性变化时
destroy 模型销毁时
sync 同步成功时
request 请求开始时
error 请求或验证失败时
invalid 验证失败时

10.3 最佳实践 #

  1. 使用 listenTo 而非 on,便于内存管理
  2. 及时解绑不再需要的事件
  3. 使用事件命名空间组织事件
  4. 避免在事件回调中直接修改模型
  5. 合理使用 oncelistenToOnce
最后更新:2026-03-28