backbone
是一个非常优秀的前端MVC框架,灵活度非常高,浏览器兼容支持的也很好,跟angularjs
相比,它显得非常轻量,相关的中文API文档,可以点击这里,然后backbone
深度依赖underscore
,详情点击这里
今天谈谈我对backbone
的一些理解.
关于Event
事件在框架里起着关键的作用,而且事件一般是独立模块,backbone
的模型,集合,视图默认都会继承事件,下面简单的说下事件的用法
on 定义一个事件
var obj = {
name: 'feenan'
};
// 使自定义对象拥有事件方法
_.extend(obj, Backbone.Event);
obj.on('go', function(){
console.log(this.name);
});
obj.trigger('go');
trigger
会触发事件,支持传递回调参数以及回调函数的上下文,在backbone
里定义事件也可以指定到单个属性,比如下面Model
里定义的change:xuwm
.
下面说说在backbone
里事件的几个特点
- 模型的任务事件触发最后都会触发
all
事件,除非传递silent:true
- 模型的任何属性改变事件都后都会触发
change
事件,除非传递silent:true
- 对集合元素的添加删除都会触发元素集合的
all
事件,除非传递silent:true
关于Model
模型在一个框架里面一般用来定义基本数据以及数据相关的操作,在backbone
里一般可以这样来定义Model
var Todo = Backbone.Model.extend({
initialize: function(){
this.on('invalid', function(){
console.log('不能通过验证!');
});
this.on('change:xuwm', function(){
console.log('change xuwm event...');
});
this.on('add', function(){
log('被添加到集合中....');
})
this.on('change', function(){
log('invoke change event!');
});
console.log('模型初始化...');
},
validate: function(attrs){
if(attrs.xuwm == 'feenan'){
return true;
}else{
return false;
}
},
defaults: function(){
return {
name: 'xuwm',
age: 20
}
}
});
extend
方法主要是在Model
的基础上扩展一些自定义的属性与方法,来看看Model
本身支持的一些让开发者重载的方法或者属性
initialize 当模型被实例化完成时,会触发此方法,一般可以在这里定义事件
defaults 定义模型的默认值
validate 定义模型属性验证方法,在这里可以对将要设置的属性进行验证,返回
true
则不修改属性,返回false
则修改属性
下面我们来使用上面定义的模型
var todo = new Todo;
todo.set({xuwm: 'feenan'});
这里要强调一下,验证属性不会发生在new
模型的时候,只会发生在实例之后,因为定义验证事件是在实例生成之后绑定的.比如上面例子里的set
方法,这是模型的一个核心方法.
关于Collection
集合是专门用来管理模型的,然后提供了数组相关的方法,跟underscore
里的方法相似,因为底层都是调用它的方法.下面是一个定义集合的例子
var TodoList = Backbone.Collection.extend({
model: Todo,
localStorage: new Backbone.LocalStorage("todos-backbone"),
rest: function(){
return this.where({done: false});
},
done: function(){
return this.where({done: true});
}
});
集合一般用来跟后台数据相关联,比如增删改查,上面例子里的后端数据用的是本地localStorage,假如不定义localStorage
属性,则后台数据请求默认用的是Backbone.ajax
来处理,这里用到了一个backbone
的一个本地存储插件backbone.localStorage.js
model
属性代表此集合关联哪个类型的模型
下面说说集合常用的方法
create 创建一个模型并保存到后台
var todos = new TodoList;
todos.create({xuwm: 'tina'});
create
方法最后调用模型的save
方法提交到后台,此处就是往本地存储里添加信息
fetch 从后台拉取数据集合
todos.fetch();
fetch
方法会调用后台服务里的read
方法,后台服务在backbone
里指Backbone.sync
模块,最终调用set
方法来依次添加数据到模型里,并绑定模型的all
事件跟集合进行关联,保证模型的修改会提醒集合的更新.
以下是添加模型时跟集合进行关联的源码js // Internal method to create a model's ties to a collection. _addReference: function(model, options) { this._byId[model.cid] = model; if (model.id != null) this._byId[model.id] = model; if (!model.collection) model.collection = this; model.on('all', this._onModelEvent, this); }, // Internal method called every time a model in the set fires an event. // Sets need to update their indexes when models change ids. All other // events simply proxy through. "add" and "remove" events that originate // in other collections are ignored. _onModelEvent: function(event, model, collection, options) { if ((event === 'add' || event === 'remove') && collection !== this) return; if (event === 'destroy') this.remove(model, options); if (model && event === 'change:' + model.idAttribute) { delete this._byId[model.previous(model.idAttribute)]; if (model.id != null) this._byId[model.id] = model; } this.trigger.apply(this, arguments); }
where 根据参数查找出相关集合列表
todos.where({xuwm: 'feenan'});
类似的数组操作方法有很多,基本上思想跟underscore
里的collection
差不多,更多的方法可以参考underscore
.
关于View
视图在backbone
里起承上启下的作用,基本上在backbone
里,集合和模型都在这里进行活动,下面给出一个定义视图的例子
var TodoView = Backbone.View.extend({
tagName: 'li',
template: _.template($('#item-template').html()),
events: {
'change .toggle': 'toggleOne',
'click .destroy': 'destroyOne'
},
initialize: function(){
this.listenTo(this.model, 'change', this.render);
this.listenTo(this.model, 'destroy', this.remove);
},
render: function(){
this.$el.html(this.template(this.model.toJSON()));
this.$el.toggleClass('done', this.model.get('done'));
this.input = this.$el;
return this;
},
toggleOne: function(){
this.model.toggle();
},
destroyOne: function(){
if(window.confirm('是否删除此任务?')){
this.model.destroy();
}
}
});
视图首先要关联页面上一个元素,通过id,class,tag
方式来绑定,然后绑定相关的dom
事件,在事件里对模型或者集合进行处理
这里说下视图里比较常用的几个属性
- initialize 初始化方法,定义一些对横型或者集合事件的绑定
- events 以一个简单的方式来统一定义视图里事件通过委托方式
- tagName/el 通过id,class,tag 来定义视图对应的页面元素
关于 Router
Router
在backbone
里比较重要,支持html5的pushstate
或者onhashchange
的方式来管理路由的改变,下面是定义一个路由的例子
var Router = Backbone.Router.extend({
routes: {
'': 'home',
'feenan': 'feenan'
},
home: function(){
todos = new TodoList;
var app = new AppView;
},
feenan: function(){
var feenanView = new FeenanView;
}
});
关于路由有几个常用的方法先介绍下
- routes 跟视图里的events有点类似,也是以key,value的形式来定义多个路由,key为hash值,value为路由回调函数
- navigate 在代码里指定要跳到哪个路由,传递
{trigger: true}
代表跳转时会执行路由回调函数
下面是使用路由的代码
var router = new Router;
Backbone.history.start();
Backbone.History
是路由的核心模块,start
方法是启动路由的关键方法,这里关键是算是浏览器的兼容以及初始路由事件的地方
关于 Sync
sync
名为同步,实为同步后台数据,其实就是一个访问后台数据的统一调用方式,提供有增删改查的方法
默认会调用Backbone.ajax
来访问后台接口,上面例子里的调用后台是用的本地存储的插件backbone.localStorage.js
,调用后台接口的地方都在backbone
内部发生
总结
本文只是对backbone
的一个简单流程的梳理,更多详细的内容请查看backbone
的源码.