这里说的定制Backbonejs,主要是定制Backbone中的sync部分,也就是最后和服务器端通信的部分。
首先得说,在Backbone里面和后端能通信的对象也就两个——Model和Collection。这俩的主要工作就是从服务器拉取数据,保存到实例中,或者把实例中的属性发送到服务器端。
上面两中类型的对象都是基于Backbone.sync来进行通信的,同时也可以定义各自的sync方法,类似这样:
Model级别的
var Message = Backbone.Model.extend({
urlRoot: '/message',
// 这么写, 打印要操作的实体, 调用系统的sync
sync: function(method, model, options){
console.log(model);
return Backbone.sync(method, model, options);
},
});
Collection级别的
var Messages = Backbone.Collection.extend({
url: '/message',
model: Message,
// 这么写, 打印要操作的实体, 调用系统的sync
sync: function(method, collection, options){
console.log(collection);
return Backbone.sync(method, collection, options);
},
});
当然,也会存在这样的需求,要修改全局的sync:
var old_sync = Backbone.sync;
Backbone.sync = function(method, model, options) {
console.log(model);
return old_sync(method, model, options);
}
所谓定制,是Backbonejs给开发者提供的可以被重写的接口。因此定制过程也得符合Backbone对sync的定义。
在 wechat 这个项目中为了保证聊天的实时性,我引入了socketio,后端使用gevent-socketio,(socketio这个东西不打算写,和主题关系不大,有需求的可以题issue)。
实时聊天的需求主要是在Message上,用户A发送一个请求,在同一聊天室内的其他用户应该立马能看见。之前有两个版本:
- 第一版是发送message时会调用messages的fetch方法,也就是用户只有发言才能看到别人发的聊天内容,代码如下:
message.save(null, {
success: function(model, response, options){
comment_box.val('');
// 重新获取,看服务器端是否有更新
// 比较丑陋的更新机制
messages.fetch({
data: {topic_id: topic_id},
success: function(){
self.message_list.scrollTop(self.message_list_div.scrollHeight);
messages.add(response);
},
});
},
});
- 第二版是引入socketio之后,在save完数据之后,通过socket把数据再次发送到服务器上的socket端,服务器再挨个发送数据到各个客户端,代码如下:
message.save(null, {
success: function(model, response, options){
comment_box.val('');
messages.add(response);
// 发送成功之后,通过socket再次发送
// FIXME: 最后可通过socket直接通信并保存
socket.emit('message', response);
},
});
// 对应着有一个socket监听, 监听服务器发来的消息
// 监听message事件,添加对话到messages中
socket.on('message', function(response) {
messages.add(response);
});
可以看得出来,上面的第二版算是比较合适了,但是还是有些别扭,数据要重复发送。因此终于到了需要定制的时刻了。
上面说了,有三种级别的定制。根据我的需求,只需要定制Model级别的就可以了,怎么定制呢?
和一开头的示例代码类似:
var Message = Backbone.Model.extend({
urlRoot: '/message',
sync: function(method, model, options){
if (method === 'create') {
socket.emit('message', model.attributes);
$('#comment').val('');
} else {
return Backbone.sync(method, model, options);
};
},
});
// 对应着上面的那个message.save后的一堆东西都可以去掉了,直接
message.save();
这样就好了,客户端只需要发送一次数据。但要记得在服务器端的监听message的接口上添加保存message的逻辑。
好了,定制就介绍这么多。关于上面提到的代码想了解上下文的,可以到我的wechat这个项目的master分支查看。
导航