backbone实例Todo源码赏析
作者:zccst
Todo实例花了我两天多的事件,为了下次再忘记,决定记录下来:
$(function(){ /******************** 模型-集合 ********************/ var Todo = Backbone.Model.extend({ defaults:function(){//defaults是函数 return {title:'apple', order:Todos.nextOrder(), done:false}; }, initialize:function(){ if(!this.get("title")){ this.set({title:this.defaults().title}); } }, validate:function(){ //console.log(this);//alert('validate'); }, toggle:function(){//每次取反 //model变,那么Todos也变,触发Collection的all事件(不是reset) this.save({done:!this.get('done')}); } }); var TodoList = Backbone.Collection.extend({ model:Todo, localStorage:new Backbone.LocalStorage("todos-backbone-my"),//存储 //默认没有,如果定义了,则被用来维护集合在正确的顺序 comparator:function(todo){ return todo.get("order");//使用order作为排序基准。order }, done:function(){//选择done字段为true的集合 //filter是underscore提供的 return this.filter(function(todo){return todo.get("done");}); }, remaining:function(){ //underscore提供,排除this中的this.done()元素列表 return this.without.apply(this, this.done()); }, nextOrder:function(){//返回该元素的下一个元素序号 if(!this.length) return 1; //underscore提供,获取最后一个元素的order值再加1 return this.last().get("order") + 1; } }); var Todos = new TodoList;//创建一个名叫Todos的全局集合列表 /******************** 视图 ********************/ var TodoView = Backbone.View.extend({ tagName : "li",//el:"todo-list", template:_.template($("#item-template").html()), events:{ 'click .toggle' : 'toggleDone', //点击切换,选中状态 'dbclick .view' : 'edit', //双击编辑 'blur .edit' : 'close', //双击编辑后,失去焦点 'keypress .edit' : 'updateOnEnter',//双击编辑后,按enter键 编辑成功 'click a.destroy': 'clear' //点击删除 }, initialize:function(){//model也就两个事件 this.listenTo(this.model, 'change', this.render); this.listenTo(this.model, 'destroy', this.remove); }, render:function(){ //console.log(this.model); this.$el.html(this.template(this.model.toJSON())); this.$el.toggleClass("done",this.model.get("done")); this.input = $(".edit");//始终指向当前被点击的行 return this; }, toggleDone:function(){//点击切换选中状态 this.model.toggle(); }, edit:function(){//双击编辑 this.$el.addClass("editing"); this.input.focus(); }, close:function(){//双击编辑后,input失去焦点 var value = this.input.val(); if(!value){ this.clear(); }else{ this.model.save({title:value});//直接save,不需要set啊 this.$el.removeClass("editing"); } }, updateOnEnter:function(e){//双击编辑后,按enter键 编辑成功 if(e.keyCode == 13) this.close(); }, clear:function(){//点击删除 this.model.destroy();//先触发destroy,后触发change事件 } }); var AppView = Backbone.View.extend({ //el:"#todoapp",el表示element,如果是id,需要#ID el:$("#todoapp"), statsTemplate : _.template($("#stats-template").html()), events:{//events是对象 'keypress #new-todo' : 'createOnEnter', //创建新的 'click #toggle-all' : 'toggleAllComplete', //全选 'click #clear-completed' : 'clearCompleted' //清空 }, initialize:function(){ this.input = this.$("#new-todo"); this.allCheckbox = this.$("#toggle-all")[0]; //触发add事件的方法 :create, fetch, add, set this.listenTo(Todos, 'add', this.addOne); //this.listenTo(Todos, 'reset', this.addAll);//触发reset :reset //只控制了footer模板,查询计算已选和未选个数 //this.listenTo(Todos, 'all', this.render); this.listenTo(Todos, 'change', this.render); this.listenTo(Todos, 'add', this.render); this.listenTo(Todos, 'remove', this.render); this.footer = this.$("footer"); this.main = this.$("#main"); //化学效应,先驻足半小时,过一遍backbone的事件监听流程 Todos.fetch();//没触发change,reset,remove事件,触发了add事件。{reset:true}触发reset事件 }, render:function(){//更新当前任务列表的状态 var done = Todos.done().length; //已选中的集合 var remaining = Todos.remaining().length; //未选中的集合 if( Todos.length ){ //Todos.length全部的集合 this.main.show(); this.footer.show(); this.footer.html(this.statsTemplate({done:done,remaining:remaining})); }else{ this.main.hide(); this.footer.hide(); } //console.log(done,remaining); this.allCheckbox.checked = !remaining; }, createOnEnter:function(e){//在events中绑定,所以参数是event if(e.keyCode != 13) return; if(!this.input.val()) return; //触发集合的add事件(绑定了addOne方法) Todos.create({'title':this.input.val()}); this.input.val(""); }, toggleAllComplete:function(){ var done = this.allCheckbox.checked; Todos.each(function(todo){ todo.save({'done':done}); }); }, clearCompleted:function(){ //清除所有被选中的(done:true的) //_.invoke(Todos.done(), 'destroy'); var arr = Todos.done();for(var item in arr){ arr[item].destroy();};//替换 return false; }, addOne:function(todo){//在initialize中绑定,所以参数是model var view = new TodoView({model:todo}); //Todo的render方法必须主动调 this.$("#todo-list").append(view.render().el); }, addAll:function(){ Todos.each(this.addOne, this); } }); var AppView = new AppView(); });
批注:AppView中initialize的add,change,remove加起来基本可以相当于all事件了。
reset的使用场景:
1,调用fetch()方法时加了{reset:true}时触发reset事件
2,直接reset({...});时触发reset事件
<div id="todoapp"> <header> <h1>Todos演示</h1> <input id="new-todo" type="text" placeholder="请输入您想做的事情?"> </header> <section id="main"> <!--for 属性规定 label 与哪个表单元素绑定--> <input id="toggle-all" type="checkbox"> <label for="toggle-all">全选</label> <ul id="todo-list"></ul> </section> <footer> <a id="clear-completed">全部清空</a> <div id="todo-count"></div> </footer> </div> <div id="instructions"> 双击编辑一个todo. </div> <div id="credits"> 由<a href="http://www.sogou.com">某某</a>创建。 <br />Rewritten by: <a href="http://addyosmani.github.com/todomvc">TodoMVC</a>. </div> <!-- Templates --> <!-- 每一项的模板 --> <script type="text/template" id="item-template"> <div class="view"> <input class="toggle" type="checkbox" <%= done ? 'checked="checked"' : '' %> /> <label><%- title %></label> <a class="destroy"></a> </div> <input class="edit" type="text" value="<%- title %>" /> </script> <!-- 底部模板 --> <script type="text/template" id="stats-template"> <% if (done) { %> <a id="clear-completed"> 有 <%= done %> 个被选中,立即清除 </a> <% } %> <div class="todo-count">还有 <b><%= remaining %></b> 个未被选中</div> </script>
如果您觉得本文的内容对您的学习有所帮助,您可以微信:
相关推荐
Chasingsun 2013-05-16
iViOLeTi 2016-01-18
Chydar 2014-07-22
ififg 2014-02-19
芋道源码 2013-07-03
蒲厷渶戀 2013-07-02
Raindan 2013-06-24
Gcalolin 2019-06-25
lancelotlewis 2013-05-16
linkincsdn 2013-05-06
我与大象的故事 2013-04-17
ifconfig 2013-04-15
VitaLemon 2012-12-15
大黑 2019-06-21
汤姆猴 2012-11-12
书弋江山 2012-10-17
Chasingsun 2019-06-20
kiven 2016-05-07