之前做一个iPad的金融项目的时候有用到Backbone,不过当时去的时候项目已经进入UAT测试阶段了,就只是改了改Bug,对Backbone框架算不上深入了解,但要说我一点都不熟悉那倒也不是,我不太喜欢这么不尴不尬地将就着,索性学习学习,整理一下好了。
网上的大牛说Backbone适合做大型的项目,小项目用Backbone有那么些杀鸡用牛刀的感觉,我目前的项目组用的是AngularJS,怎么说呢?个人觉得AngularJS是属于通吃那一类的,也说不出理由,纯粹个人感觉,不过当时写那个iPad项目的时候用了Backbone确实感觉整个结构还蛮清晰的,虽然使用的时候View层和Controller层并没有区分得很清楚。
好歹我那时候还一腔热血地买了本《Backbone.js实战》来看呢?总是不能浪费了。
书上一开头先是说underscore再说backbone,我表示这种把API往书里搬真的是很骗钱啊!所以我打算先从MVC的架构入手,先把整体架构搞清楚了。
Model数据模型
1.初始化
<!DOCTYPE html> <html> <head> <script src="./js/underscore-1.8.2-min.js"></script> <script src="./js/backbone-1.1.2-min.js"></script> </head> <body> <script> var student = Backbone.Model.extend({ initialize:function(){ intNum++; console.log("you have built " + intNum + " object"); } }); var intNum = 0; var stuA = new student(); var stuB = new student(); </script> </body> </html>
结果
2.赋值,变量的设置与读取
注意set()和get()
<!DOCTYPE html> <html> <head> <script src="./js/underscore-1.8.2-min.js"></script> <script src="./js/backbone-1.1.2-min.js"></script> </head> <body> <script> var student = Backbone.Model.extend({ initialize:function(){ //construct code } }); var stuA = new student(); stuA.set({ Code:"01", Name:"Larry", Score:"90" }); console.log(stuA.get("Code")); console.log(stuA.get("Name")); console.log(stuA.get("Score")); </script> </body> </html>
结果
3.定义函数
注意escape()
<!DOCTYPE html> <html> <head> <script src="./js/underscore-1.8.2-min.js"></script> <script src="./js/backbone-1.1.2-min.js"></script> </head> <body> <script> var student = Backbone.Model.extend({ initialize:function(){ //construct code }, printLog:function(){ console.log(this.get("Code")); console.log(this.get("Name")); console.log(this.get("Score")); console.log(this.escape("Code")); console.log(this.escape("Name")); console.log(this.escape("Score")); } }); var stuA = new student(); stuA.set({ Code:"01", Name:"Larry", Score:"90" }); stuA.printLog(); </script> </body> </html>
结果
4.事件监听
注意on()方法
<!DOCTYPE html> <html> <head> <script src="./js/underscore-1.8.2-min.js"></script> <script src="./js/backbone-1.1.2-min.js"></script> </head> <body> <script> var student = Backbone.Model.extend({ initialize:function(){ this.on("change:Name",function(){ var oldname = this.previous("Name"); var newname = this.get("Name"); if(oldname != newname){ console.log(oldname + "," + newname); } }); }, defaults:{ Code:"", Name:"Devin", Score:"" } }); var stuA = new student(); stuA.set("Name","Larry"); </script> </body> </html>
5.数据验证
开启数据验证
<!DOCTYPE html> <html> <head> <script src="./js/underscore-1.8.2-min.js"></script> <script src="./js/backbone-1.1.2-min.js"></script> </head> <body> <script> var student = Backbone.Model.extend({ initialize:function(){ this.on("invalid",function(model,error){ console.log(error); }); }, validate:function(attrs){ if(!_.isString(attrs.Name)){ return 'the name must be String'; } if(!_.isNumber(attrs.Score)){ return 'the score must be Number'; } }, defaults:{ Code:"10001", Name:"Devin", Score:"100" } }); var stuA = new student(); stuA.set({ Code:"10105", Name:12345, Score:600 },{"validate":true}); console.log(stuA.toJSON()); </script> </body> </html>
结果
将set()方法里的第二个参数的validate改为silent即可关闭数据验证
stuA.set({ Code:"10105", Name:12345, Score:600 },{"silent":true});
6.删除数据
obj.unset(attrName) 删除指定名称的数据,删除属性
obj.clear() 清除对象中的全部数据
<!DOCTYPE html> <html> <head> <script src="./js/underscore-1.8.2-min.js"></script> <script src="./js/backbone-1.1.2-min.js"></script> </head> <body> <script> var student = Backbone.Model.extend({ initialize:function(){ //construct code }, defaults:{ Code:"10001", Name:"Devin", Score:100 } }); var stuA = new student(); stuA.set({ Code:"10105", Name:"Larry", Score:600 }); //unset() stuA.unset("Name"); console.log(stuA.get("Name")); console.log(stuA.toJSON()); //previous stuA.set("Name",stuA.previous("Name")); console.log(stuA.toJSON()); //clear() stuA.clear(); console.log(stuA.toJSON()); </script> </body> </html>
结果
7.attributes属性
<!DOCTYPE html> <html> <head> <script src="./js/underscore-1.8.2-min.js"></script> <script src="./js/backbone-1.1.2-min.js"></script> </head> <body> <script> var student = Backbone.Model.extend({ initialize:function(){ //construct code }, defaults:{ Code:"10001", Name:"Devin", Score:100 } }); var stuA = new student(); stuA.set({ Code:"10105", Name:"Larry", Score:600 }); //输出attributes对象 console.log(stuA.attributes); //输出attributes的每一项 var attrs = stuA.attributes; for(var i in attrs){ console.log(i + ":" + stuA.attributes[i]); } </script> </body> </html>
结果
8.previous()和previousAttributes()
<!DOCTYPE html> <html> <head> <script src="./js/underscore-1.8.2-min.js"></script> <script src="./js/backbone-1.1.2-min.js"></script> </head> <body> <script> var student = Backbone.Model.extend({ initialize:function(){ //construct code }, defaults:{ Code:"10001", Name:"Devin", Score:100 } }); var stuA = new student(); stuA.set({ Code:"10105", Name:"Larry", Score:600 }); console.log(stuA.toJSON()); console.log(stuA.previousAttributes()); console.log("====I am spliter====="); stuA.set({ Code:"10106", Name:"Lucy", Score:602 }); console.log(stuA.toJSON()); console.log(stuA.previousAttributes()); </script> </body> </html>
结果
除此之外,在Model中还有一些ajax方法和属性
save() 发送数据方法
wait属性 对发送数据进行有效性验证
fetch() 从服务器获取数据
destroy() 从服务器删除数据
Collection模型集合
我一直以为C是Controller的,但是在Backbone中C是Collection,说白了,Model只是一个数据模型,真正要量产复制的还是由Collection来完成。
一 创建集合对象
1.自定义集合对象
<!DOCTYPE html> <html> <head> <script src="./js/underscore-1.8.2-min.js"></script> <script src="./js/backbone-1.1.2-min.js"></script> </head> <body> <script> var student = Backbone.Model.extend({ defaults:{ Code:"", Name:"", Score:"" } }); var stuCollection = Backbone.Collection.extend({ model:student }); var stuA = [ { Code:"10101", Name:"Larry", Score:"100" }, { Code:"10102", Name:"Devin", Score:"101" }, { Code:"10103", Name:"Lucy", Score:"102" } ]; var stus = new stuCollection(stuA); for(var i=0;i<stus.models.length;i++){ console.log(stus.models[i].toJSON()); } </script> </body> </html>
结果
注意观察stus.models,在stus定义的时候,我们给这个collection装入了我们定义好的stuA这个对象数组,而这个collection的model又是我们之前定义好的student,所以stus的model为student,它的collection为stuA,我们用stus.models就可以访问到stuA的所有数据
2.实例化集合对象
我们可以换一种new的方式,不必定义Collection,直接在new的时候调用Backbone.Collection()方法就好,并在方法内指认model。
<!DOCTYPE html> <html> <head> <script src="./js/underscore-1.8.2-min.js"></script> <script src="./js/backbone-1.1.2-min.js"></script> </head> <body> <script> var student = Backbone.Model.extend({ defaults:{ Code:"", Name:"", Score:"" } }); //var stuCollection = Backbone.Collection.extend({ // model:student //}); var stuA = [ { Code:"10101", Name:"Larry", Score:"100" }, { Code:"10102", Name:"Devin", Score:"101" }, { Code:"10103", Name:"Lucy", Score:"102" } ]; var stus = new Backbone.Collection(stuA,{ model:student }); for(var i=0;i<stus.models.length;i++){ console.log(stus.models[i].toJSON()); } </script> </body> </html>
结果
3.自定义集合方法
示例:筛选分数在400分以上的学生信息进行显示
<!DOCTYPE html> <html> <head> <script src="./js/underscore-1.8.2-min.js"></script> <script src="./js/backbone-1.1.2-min.js"></script> </head> <body> <script> var student = Backbone.Model.extend({ defaults:{ Code:"", Name:"", Score:0 } }); var stuCollection = Backbone.Collection.extend({ model:student, good:function(){ return this.filter(function(stu){ return stu.get("Score")>400; }); } }); var stuA = [ { Code:"10101", Name:"Larry", Score:100 }, { Code:"10102", Name:"Devin", Score:500 }, { Code:"10103", Name:"Lucy", Score:500 } ]; var stus = new stuCollection(stuA); var stug = stus.good(); for(var i=0;i<stus.models.length;i++){ console.log(stus.models[i].toJSON()); } console.log("=====I am spliter====="); for(var i=0;i<stug.length;i++){ console.log(stug[i].toJSON()); } </script> </body> </html>
结果
二 操作集合中模型对象
1.移除集合对象中的模型
obj.remove(models,options) 从指定的集合对象中移除一个或多个模型对象
obj.pop(options) 移除集合对象中最后一个模型对象
obj.shift(options) 移除集合对象中首个模型对象
<!DOCTYPE html> <html> <head> <script src="./js/underscore-1.8.2-min.js"></script> <script src="./js/backbone-1.1.2-min.js"></script> </head> <body> <script> var student = Backbone.Model.extend({ defaults:{ Code:"", Name:"", Score:0 } }); var stuCollection = Backbone.Collection.extend({ model:student }); var stuA = [ { Code:"10101", Name:"Larry", Score:100 }, { Code:"10102", Name:"Devin", Score:500 }, { Code:"10103", Name:"Lucy", Score:500 }, { Code:"10104", Name:"Jeff", Score:550 }, { Code:"10105", Name:"Lei", Score:600 } ]; var stus = new stuCollection(stuA); for(var i=0;i<stus.models.length;i++){ console.log(stus.models[i].toJSON()); } console.log("=====I am spliter====="); stus.shift(); for(var i=0;i<stus.models.length;i++){ console.log(stus.models[i].toJSON()); } console.log("=====I am spliter====="); stus.pop(); for(var i=0;i<stus.models.length;i++){ console.log(stus.models[i].toJSON()); } console.log("=====I am spliter====="); stus.remove(stus.models[2]); for(var i=0;i<stus.models.length;i++){ console.log(stus.models[i].toJSON()); } </script> </body> </html>
结果
2.添加集合对象中的模型
obj.add(models,options) 在集合对象的指定位置插入模型对象,如果没有指定位置i,默认为集合对象的尾部
obj.push(models,options) 向集合对象的尾部插入模型对象
obj.unshift(models,options) 向集合对象的头部插入模型对象
<!DOCTYPE html> <html> <head> <script src="./js/underscore-1.8.2-min.js"></script> <script src="./js/backbone-1.1.2-min.js"></script> </head> <body> <script> var student = Backbone.Model.extend({ defaults:{ Code:"", Name:"", Score:0 } }); var stuCollection = Backbone.Collection.extend({ model:student }); var stuA = [ { Code:"10101", Name:"Larry", Score:100 }, { Code:"10102", Name:"Devin", Score:500 }, { Code:"10103", Name:"Lucy", Score:500 } ]; var newStu = [ { Code:"10104", Name:"Jeff", Score:550 }, { Code:"10105", Name:"Lei", Score:600 }, { Code:"10106", Name:"Felix", Score:530 }, { Code:"10107", Name:"Annie", Score:530 } ]; var stus = new stuCollection(stuA); for(var i=0;i<stus.models.length;i++){ console.log(stus.models[i].toJSON()); } console.log("=====I am spliter====="); stus.unshift(newStu[1]); for(var i=0;i<stus.models.length;i++){ console.log(stus.models[i].toJSON()); } console.log("=====I am spliter====="); stus.add(newStu[0],{at:4}); for(var i=0;i<stus.models.length;i++){ console.log(stus.models[i].toJSON()); } console.log("=====I am spliter====="); stus.push(newStu[2]); stus.push(newStu[3]); for(var i=0;i<stus.models.length;i++){ console.log(stus.models[i].toJSON()); } </script> </body> </html>
结果
3.查找集合对象中的模型
obj.get(id) 通过id来查找(ID是在模型对象产生时生成的标志,用于与服务器保持同步的编号)
obj.at(index) 通过制定索引号获取集合中某一个模型对象
obj.findWhere(attrs) 查找与属性名称和属性值相配的第一个模型对象
obj.where(attrs,first) 查找与属性名称和属性值相配的第一个模型或多个模型对象(当first为true时只返回第一个)
<!DOCTYPE html> <html> <head> <script src="./js/underscore-1.8.2-min.js"></script> <script src="./js/backbone-1.1.2-min.js"></script> </head> <body> <script> var student = Backbone.Model.extend({ defaults:{ Code:"", Name:"", Score:0 }, idAttribute:"Code" }); var stuCollection = Backbone.Collection.extend({ model:student }); var stuA = [ { Code:"10101", Name:"Larry", Score:100 }, { Code:"10102", Name:"Devin", Score:500 }, { Code:"10103", Name:"Lucy", Score:500 }, { Code:"10104", Name:"Jeff", Score:550 }, { Code:"10105", Name:"Lei", Score:600 }, { Code:"10106", Name:"Felix", Score:530 }, { Code:"10107", Name:"Annie", Score:530 } ]; var stus = new stuCollection(stuA); for(var i=0;i<stus.models.length;i++){ console.log(stus.models[i].toJSON()); } console.log("=====search result====="); var result = stus.get(10106); console.log(result); console.log("=====I am get spliter====="); result = stus.at(3); console.log(result); console.log("=====I am at spliter====="); result = stus.findWhere({Score:500}); console.log(result); console.log("=====I am findWhere spliter====="); result = stus.where({Score:500}); console.log(result); console.log("=====I am where spliter====="); </script> </body> </html>
结果
4.集合中模型对象的排序
obj.sort(options) 必须在实例化集合对象时添加一个名为"comparator"的方法,以此来规定排序规则。
<!DOCTYPE html> <html> <head> <script src="./js/underscore-1.8.2-min.js"></script> <script src="./js/backbone-1.1.2-min.js"></script> </head> <body> <script> var student = Backbone.Model.extend({ defaults:{ Code:"", Name:"", Score:0 }, idAttribute:"Code" }); var stuCollection = Backbone.Collection.extend({ model:student, comparator:function(model_1,model_2){ var compResult = model_1.get('Score')>model_2.get('Score'); return compResult?0:1; } }); var stuA = [ { Code:"10102", Name:"Devin", Score:500 }, { Code:"10104", Name:"Jeff", Score:550 }, { Code:"10103", Name:"Lucy", Score:500 }, { Code:"10107", Name:"Annie", Score:530 }, { Code:"10105", Name:"Lei", Score:600 }, { Code:"10106", Name:"Felix", Score:530 }, { Code:"10101", Name:"Larry", Score:800 } ]; var stus = new stuCollection(stuA); for(var i=0;i<stus.models.length;i++){ console.log(stus.models[i].toJSON()); } console.log("=====I am spliter====="); stus.sort(); for(var i=0;i<stus.models.length;i++){ console.log(stus.models[i].toJSON()); } </script> </body> </html>
结果
三 与服务器交互集合中的模型对象
fetch() 从服务器获取数据
create() 与服务器同步数据
View视图
Model和Collection都属于底层的数据处理,真正与页面交互的是View。
View的核心功能是处理数据业务逻辑,绑定DOM元素事件,渲染模型或集合数据。
一 视图基础
在定义一个视图对象之前,需要构建一个视图类
在构建类时,可以设置el属性关联DOM中的元素
也可以指定与视图相关的模型或集合类名,实现各个类之间对象的数据互访问
1.定义视图对象
记得先引入jQuery,我们在做DOM操作的时候会使用到jQuery
注意render()方法的写法和用法
<!DOCTYPE html> <html> <head> <script src="./js/jquery-1.11.3.min.js"></script> <script src="./js/underscore-1.8.2-min.js"></script> <script src="./js/backbone-1.1.2-min.js"></script> <style> .test{color:red;} </style> </head> <body> <script> var testView = Backbone.View.extend({ id:"show", className:"test", render:function(content){ this.el.innerHTML = content; document.body.appendChild(this.el); } }); var test = new testView(); test.render("Hello,World!"); </script> </body> </html>
结果
可以看到在DOM上生成了节点,id和class都是我们用代码动态添加上去的
2.视图对象访问模型对象
<!DOCTYPE html> <html> <head> <script src="./js/jquery-1.11.3.min.js"></script> <script src="./js/underscore-1.8.2-min.js"></script> <script src="./js/backbone-1.1.2-min.js"></script> <style> .test{color:red;} </style> </head> <body> <div id="show" class="test"></div> <script> var student = Backbone.Model.extend({ defaults:{ Code:"", Name:"", Score:0 } }); var stus = new student({ Code:"10101", Name:"Larry", Score:750 }); var stusView = Backbone.View.extend({ el:"#show", render:function(){ this.el.innerHTML = JSON.stringify(this.model); } }); var stuv = new stusView({model:stus}); stuv.render(); </script> </body> </html>
结果
3.视图对象访问集合对象
<!DOCTYPE html> <html> <head> <script src="./js/jquery-1.11.3.min.js"></script> <script src="./js/underscore-1.8.2-min.js"></script> <script src="./js/backbone-1.1.2-min.js"></script> <style> .test{color:red;} </style> </head> <body> <div id="show" class="test"></div> <script> var stuModel = [ { Code:"10101", Name:"Larry", Score:750 }, { Code:"10102", Name:"Felix", Score:600 }, { Code:"10103", Name:"Devin", Score:550 } ]; var stuList = new Backbone.Collection(stuModel); var stuView = Backbone.View.extend({ el:"#show", render:function(){ var curlist = this.collection.models; for(var i=0;i<curlist.length;i++){ this.el.innerHTML += JSON.stringify(curlist[i]) + "<br />"; } } }); var stuv = new stuView({collection:stuList}); stuv.render(); </script> </body> </html>
结果
二 视图中的模板
1.处理逻辑的模板
<%= %> 区域内的变量会在调用模板时被以字典方式传入的对应值所取代。支持简单的JS语句
<!DOCTYPE html> <html> <head> <script src="./js/jquery-1.11.3.min.js"></script> <script src="./js/underscore-1.8.2-min.js"></script> <script src="./js/backbone-1.1.2-min.js"></script> <style> body{font-size:14px;} div{width:260px; padding:5px;} </style> </head> <body> <div id="score"></div> <script type="text/template" id="score-tpl"> <%= score > 600 ? "good job":"just so so" %> </script> <script> var stuView = Backbone.View.extend({ el:$("#score"), initialize:function(){ this.template = _.template($("#score-tpl").html()); }, render:function(pscore){ this.$el.html(this.template({score:pscore})); } }); var stuv = new stuView(); stuv.render(600); </script> </body> </html>
结果
2.显示多项内容的模板
<!DOCTYPE html> <html> <head> <script src="./js/jquery-1.11.3.min.js"></script> <script src="./js/underscore-1.8.2-min.js"></script> <script src="./js/backbone-1.1.2-min.js"></script> <style> body{font-size:12px;} ul{list-style-type:none; padding:0; margin:0;} </style> </head> <body> <ul id="ulshowstus"></ul> <script type="text/template" id="stus-tpl"> <li>Code:<%=Code %></li> <li>Name:<%=Name %></li> <li>Score:<%=Score %></li> </script> <script> var student = Backbone.Model.extend({ defaults:{ Code:"", Name:"", Score:0 } }); var stus = new student({ Code:"10101", Name:"Larry", Score:750 }); var stuView = Backbone.View.extend({ el:$("#ulshowstus"), initialize:function(){ this.template = _.template($("#stus-tpl").html()); }, render:function(){ this.$el.html(this.template(this.model.toJSON())); } }); var stuv = new stuView({model:stus}); stuv.render(); </script> </body> </html>
结果
3.自定义模板变量标记
我们可以使用{{}}标记来代替%
<!DOCTYPE html> <html> <head> <script src="./js/jquery-1.11.3.min.js"></script> <script src="./js/underscore-1.8.2-min.js"></script> <script src="./js/backbone-1.1.2-min.js"></script> <style> body{font-size:12px;} ul{list-style-type:none; padding:0; margin:0;} </style> </head> <body> <ul id="ulshowstus"></ul> <script type="text/template" id="stus-tpl"> <li>Code:{{Code}}</li> <li>Name:{{Name}}</li> <li>Score:{{Score}}</li> </script> <script> _.templateSettings = { interpolate:/{{(.+?)}}/g }; var student = Backbone.Model.extend({ defaults:{ Code:"", Name:"", Score:0 } }); var stus = new student({ Code:"10101", Name:"Larry", Score:750 }); var stuView = Backbone.View.extend({ el:$("#ulshowstus"), initialize:function(){ this.template = _.template($("#stus-tpl").html()); }, render:function(){ this.$el.html(this.template(this.model.toJSON())); } }); var stuv = new stuView({model:stus}); stuv.render(); </script> </body> </html>
结果
三 视图中的元素事件
1.视图中简单事件绑定
<!DOCTYPE html> <html> <head> <script src="./js/jquery-1.11.3.min.js"></script> <script src="./js/underscore-1.8.2-min.js"></script> <script src="./js/backbone-1.1.2-min.js"></script> <style> body{font-size:12px;} div{width:260px;text-align:center;padding:5px;} .changed{border:solid 1px #555;} </style> </head> <body> <script> var stuView = Backbone.View.extend({ el:$("body"), initialize:function(){ this.render(); }, render:function(){ this.$el.append('<div id="backbone">Hello,World!</div>'); }, events:{ "click div#backbone":"togcls" }, togcls:function(){ $("#backbone").toggleClass("changed"); } }); var stuv = new stuView(); </script> </body> </html>
结果
点击前
点击后
2.绑定视图模板的多个事件
<!DOCTYPE html> <html> <head> <script src="./js/jquery-1.11.3.min.js"></script> <script src="./js/underscore-1.8.2-min.js"></script> <script src="./js/backbone-1.1.2-min.js"></script> <style> body{font-size:12px;} div{width:260px;text-align:center;padding:5px;} .changed{border:solid 1px #555;} </style> </head> <body> <div id="main"></div> <script type="text/template" id="main-tpl"> <div id="backbone"><%=mess%></div> <input id="btnshow" type="button" value="click me" /> </script> <script> var stuView = Backbone.View.extend({ el:$("#main"), initialize:function(){ this.template = _.template($("#main-tpl").html()); this.render(); }, render:function(){ this.$el.html(this.template({ mess:"Hello,World!" })); }, events:{ "click div#backbone":"togcls", "click input#btnshow":"toggle" }, togcls:function(){ $("#backbone").toggleClass("changed"); }, toggle:function(){ $("#backbone").toggle(); } }); var stuv = new stuView(); </script> </body> </html>
结果
button被点击前
button被点击后
3.动态绑定和取消视图中的事件
delegateEvents() undelegateEvents()
<!DOCTYPE html> <html> <head> <script src="./js/jquery-1.11.3.min.js"></script> <script src="./js/underscore-1.8.2-min.js"></script> <script src="./js/backbone-1.1.2-min.js"></script> <style> body{font-size:12px;} div{width:260px;text-align:center;padding:5px;} .changed{border:solid 1px #555;} </style> </head> <body> <div id="main"></div> <script type="text/template" id="main-tpl"> <div id="backbone">Hello,World!</div> <input id="btn_a" type="button" value="change style" /> <input id="btn_b" type="button" value="cancel bind" /> <input id="btn_c" type="button" value="rebind" onclick="stuv.rebind()" /> </script> <script> var stuView = Backbone.View.extend({ el:$("#main"), initialize:function(){ this.template = _.template($("#main-tpl").html()); this.render(); }, render:function(){ this.$el.html(this.template()); }, rebind:function(){ this.delegateEvents(this.events); }, events:{ "click input#btn_a":"btnclick_a", "click input#btn_b":"btnclick_b" }, btnclick_a:function(){ $("#backbone").toggleClass("changed"); }, btnclick_b:function(){ this.undelegateEvents(); } }); var stuv = new stuView(); </script> </body> </html>
Backbone的笔记就到这里了,在学习的过程当中我发现,Backbone中模板的写法和Handlebars有点像,发现越来越喜欢Backbone了!
以上所有代码示例均来自《Backbone.js实战》 陶国荣著 机械工业出版社
虽然不是我的原创,但是代码是我一行一行手打出来的,每一个示例都亲自测试,调试,每一个结果都是我自己运行后截图上传上来的,如果有人转载,请您标注一下出处。
我的很多博文也是摘抄自很多地方的,我都会在页尾标明文章来源。
总结的好辛苦啊!但是我相信这辛苦一定值得!
参考文章:
http://www.cnblogs.com/yexiaochai/archive/2013/07/27/3219402.html
http://www.css88.com/doc/backbone/