本文转自:http://weakfi.iteye.com/blog/1391990
什么是backbone
backbone不是脊椎骨,而是帮开发重量级的javascript应用之框架。
要害提供了3单东西:1、models(模型)
2、collections(集合) 3、views(视图)
backbone.js文件本身非常粗,压缩后止生5.3KB,作为一个框架级别的着力JS文件,这个数字格外吓人。
除外,这个JS还须靠让其它一个JS文件:underscore.js(包含多家伙方法,集合操作,js模板等等)。
简介
故Backbone.Model表示以中兼有数据,models中之数目好创建、校验、销毁和封存至服务端。
当models中值为改变时自动触发一个”change”事件、所有用于展示models数据的views都见面侦听到这个事件,然后进行再渲染。
Backbone.Collection和咱们平素点的JAVA集合类相似,具有增加元素,删除元素,获取长度,排序,比较等同样名目繁多工具方法,说白了就是是一个封存models的集合类。
Backbone.View中得以绑定dom
el和客户端事件。页面中之html就是经views的render方法渲染出来的,当新建一个view的时段经过要传进一个model作为数据,例如:
Js代码
)
-
var view = new EmployeeView({model:employee});
var view = new EmployeeView({model:employee});
也就是说model就是为这种办法跟view进行关联的。
特点
开创models或者views的语法:extends,相当给类继承
models的创造,销毁,校验等一律多级反都见面硌相应的风波
示例
需求:之所以backbone.js和jquery实现一个但编制的员工信息表。
功能:1、录入员工信息。2、删除员工信息。3、双击表格可对员工信息进行修改。4、能针对职工信息进行实用校验。5、能对职工信息进行持久化。
设计:
故Employee类(继承自Backbone.Model)表示员工信息,包含ID、姓名、性别、年龄与位置字段。
Js代码
)
- window.Employee = Backbone.Model.extend({
- // 模型值校验
- validate:function(attrs){
- for(var key in attrs){
- if(attrs[key] == ”){
- return key + “不可知也空”;
- }
- if(key == ‘age’ && isNaN(attrs.age)){
- return “年龄要是数字”;
- }
- }
- }
-
});
window.Employee = Backbone.Model.extend({ // 模型值校验 validate:function(attrs){ for(var key in attrs){ if(attrs[key] == ''){ return key + "不能为空"; } if(key == 'age' && isNaN(attrs.age)){ return "年龄必须是数字"; } } } });
声明Employee类之后虽可以激增一个Employee的示范对象了:
Js代码
)
-
var employee = new Employee();
var employee = new Employee();
Employee类中不要声明ID、姓名等事务字段。当需要给employee设置这些信息上,只需要调用
Js代码
)
-
employee.set({‘id’:1,’name’:’Jason’});
employee.set({‘id’:1,’name’:’Jason’});
自然,如果用对employee的音进行校验,需要给Employee类配置一个validate方法,这个艺术的参数attrs就是set进去的json数据。这样,当employee里面的数额每次发反之时段还见面预先调用这个validate方法。
Model类定义好下虽足以起来定义集合类了,在集合类里面可以本着内部的每个Model进行追加,删除等同样多元操作,还可以调用fetch方法从server端获取集合的初始值。
Js代码
)
- window.EmployeeList = Backbone.Collection.extend({
- model : Employee,
- // 持久化到地方数据库
- localStorage: new Store(“employees”),
- });
-
window.Employees = new EmployeeList();
window.EmployeeList = Backbone.Collection.extend({ model : Employee, // 持久化到本地数据库 localStorage: new Store("employees"), }); window.Employees = new EmployeeList();
安装
localStorage属性后Employees里面的数额自动会同步保存到本地数据库中,每当调用Employees.fetch()后而见面起localStorage里面恢复数据。
View类主要担负整个与界面相关的做事,比如绑定html模板,绑定界面元素的波,初始的渲染,模型值改变后的再度渲染和界面元素的销毁等:
Js代码
)
- window.EmployeeView = Backbone.View.extend({
- tagName : ‘tr’,
- template : _.template($(‘#item-template’).html()),
- events : {
- “dblclick td” : “edit”,
- “blur input,select” : “close”,
- “click .del” : “clear”,
- },
- initialize : function(){
- // 每次换代模型后再渲染
- this.model.bind(‘change’, this.render, this);
- // 每次去模型之后自动转换除了UI
- this.model.bind(‘destroy’, this.remove, this);
- },
- setText : function(){
- var model = this.model;
- this.input = $(this.el).find(‘input,select’);
- this.input.each(function(){
- var input = $(this);
- input.val(model.get(input.attr(“name”)));
- });
- },
- close: function(e) {
- var input = $(e.currentTarget);
- var obj = {};
- obj[input.attr(‘name’)] = input.val();
- this.model.save(obj);
- $(e.currentTarget).parent().parent().removeClass(“editing”);
- },
- edit : function(e){
- // 给td加上editing样式
- $(e.currentTarget).addClass(‘editing’).find(‘input,select’).focus();
- },
- render: function() {
- $(this.el).html(this.template(this.model.toJSON()));
- // 把每个单元格的价赋予隐藏的输入框
- this.setText();
- return this;
- },
- remove: function() {
- $(this.el).remove();
- },
- clear: function() {
- this.model.destroy();
- }
-
});
window.EmployeeView = Backbone.View.extend({
tagName : 'tr', template : _.template($('#item-template').html()), events : { "dblclick td" : "edit", "blur input,select" : "close", "click .del" : "clear", }, initialize : function(){ // 每次更新模型后重新渲染 this.model.bind('change', this.render, this); // 每次删除模型之后自动移除UI this.model.bind('destroy', this.remove, this); }, setText : function(){ var model = this.model; this.input = $(this.el).find('input,select'); this.input.each(function(){ var input = $(this); input.val(model.get(input.attr("name"))); }); }, close: function(e) { var input = $(e.currentTarget); var obj = {}; obj[input.attr('name')] = input.val(); this.model.save(obj); $(e.currentTarget).parent().parent().removeClass("editing"); }, edit : function(e){ // 给td加上editing样式 $(e.currentTarget).addClass('editing').find('input,select').focus(); }, render: function() { $(this.el).html(this.template(this.model.toJSON())); // 把每个单元格的值赋予隐藏的输入框 this.setText(); return this; }, remove: function() { $(this.el).remove(); }, clear: function() { this.model.destroy(); } });
这个看似里的代码比较多,但要与界面的渲染有关。一个EmployeeView对象对应table里面的一个tr元素。每次new一个EmployeeView对象的上还见面先调用initialize方法,这个法中绑定的风波确保了tr元素对应的model值每次发生改变或被剔除时犹见面一起到界面。也就是说当每次操作界面对数码开展改动后都是先管当下底改保存及view绑定的model对象中,然后model里面的事件机制会活动触发一个”change”事件对界面进行改动。
template中使的点子_.template($(‘#item-template’).html())是前方提到的underscore.js中提供一个家伙方法,可以透过界面的HTML模板与一个JSON生成动态的HTML,说白了就是是将JSON里面的值填充到HTML模板被对应的占位符里面去,牛X的是HTML模板里面支持部分常用的逻辑表达式如if,else,foreach等:
Html代码
)
- <script type=”text/template” id=”item-template”>
- <td><%= eid %></td>
- <td class=”username”>
- <div class=”display”><%= username %></div>
- <div class=”edit”><input class=”username” name=”username”></input></div>
- </td>
- <td class=”sex”>
- <div class=”display”><%= sex==”1″ ? “女”:”男” %></div>
- <div class=”edit”>
- <select name=”sex” class=”sex” style=”width:45px”>
- <option value=”0″>男</option><option value=”1″>女</option>
- </select>
- </div>
- </td>
- <td class=”age”>
- <div class=”display”><%= age %></div>
- <div class=”edit”>
- <input class=”age” name=”age”></input>
- </div>
- </td>
- <td class=”position”>
- <div class=”display”><%= position %></div>
- <div class=”edit”>
- <input class=”position” name=”position”></input>
- </div>
- </td>
- <td>
- <a href=”#” class=”del”>删除</a>
- </td>
-
</script>
<script type="text/template" id="item-template"> <td><%= eid %></td> <td class="username"> <div class="display"><%= username %></div> <div class="edit"><input class="username" name="username"></input></div> </td> <td class="sex"> <div class="display"><%= sex=="1" ? "女":"男" %></div> <div class="edit"> <select name="sex" class="sex" style="width:45px"> <option value="0">男</option><option value="1">女</option> </select> </div> </td> <td class="age"> <div class="display"><%= age %></div> <div class="edit"> <input class="age" name="age"></input> </div> </td> <td class="position"> <div class="display"><%= position %></div> <div class="edit"> <input class="position" name="position"></input> </div> </td> <td> <a href="#" class="del">删除</a> </td> </script>
setText方法主要承担将model里面的数码设置到每个tr里面的隐藏输入域里面。
close方法为绑定到了input和select元素的blur事件中。当用户对单元格数据进行改动后都见面拿鼠标点击到界面其他地方然后输入框会自动隐藏并且将修改的多少展示在表上面。close方法首先从脚下吃编的素中拿到新型值,然后封装成一个靶,调用model的save方法后率先实施model的validate方法,如果校验通过则保留及地方存储并触及”change”事件。
终极还索要一个主界面View,这个View主要绑定了界面中之录入表单的“增加”按钮事件,Employees的连锁事件与页面初始化时于地方存储着回复数据:
Js代码
)
- window.AppView = Backbone.View.extend({
- el : $(“#app”),
- events : {
- “click .#add-btn” : “createOnEnter”
- },
- // 绑定collection的相干事件
- initialize: function() {
- Employees.bind(‘add’, this.addOne, this);
- // 调用fetch的时触发reset
- Employees.bind(‘reset’, this.addAll, this);
- Employees.fetch();
- },
- createOnEnter : function(e) {
- var employee = new Employee();
- var attr = {};
- $(‘#emp-form input,#emp-form select’).each(function(){
- var input = $(this);
- attr[input.attr(‘name’)] = input.val();
- });
- employee.bind(‘error’,function(model,error){
- alert(error);
- });
- // set方法被见面活动调用model的validate方法开展校验,如果不通过则归false
- if(employee.set(attr)){
- Employees.create(employee);
- }
- },
- addOne : function(employee){
- employee.set({“eid”:employee.get(“eid”)||Employees.length});
- employee.bind(‘error’,function(model,error){
- alert(error);
- });
- var view = new EmployeeView({model:employee});
- $(“.emp-table tbody”).append(view.render().el);
- },
- addAll : function(){
- Employees.each(this.addOne);
- }
-
});
window.AppView = Backbone.View.extend({
el : $("#app"), events : { "click .#add-btn" : "createOnEnter" }, // 绑定collection的相关事件 initialize: function() { Employees.bind('add', this.addOne, this); // 调用fetch的时候触发reset Employees.bind('reset', this.addAll, this); Employees.fetch(); }, createOnEnter : function(e) { var employee = new Employee(); var attr = {}; $('#emp-form input,#emp-form select').each(function(){ var input = $(this); attr[input.attr('name')] = input.val(); }); employee.bind('error',function(model,error){ alert(error); }); // set方法中会自动调用model的validate方法进行校验,如果不通过则返回false if(employee.set(attr)){ Employees.create(employee); } }, addOne : function(employee){ employee.set({"eid":employee.get("eid")||Employees.length}); employee.bind('error',function(model,error){ alert(error); }); var view = new EmployeeView({model:employee}); $(".emp-table tbody").append(view.render().el); }, addAll : function(){ Employees.each(this.addOne); } });
initialize方法吃绑定了Employees的add和reset事件,也就是说每当往Employees丁补充加一个model的时光都见面调用AppView的addOne方法,这个方法主要绑定了model的error事件以及将EmployeeView生成的html插入到界面被的适龄岗位。
OK,万事俱备,只少启动,整个应用之初始化方法就是是AppView的initialize方法,因此只待新建一个AppView就好了:
Js代码
)
-
window.App = new AppView();
window.App = new AppView();
通示例的JS代码很少,加上注释只来100执左右,感兴趣之可下载看。由于示例使用到了地面存储,所以并非就此IE运行示例,你了解的。
- backbone.zip
(90.8 KB) - 下载次数: 3129