在前两篇文章中,我们已经对这个todos的功能、数据模型以及各个模块的实现细节进行了分析,这篇文章我们要对前面的分析进行一个整合。前面我们说过,有了肉和菜,剩下的就是要怎么吃。我个人倾向于菜和肉一起吃,这样不会觉得腻 :-)
首先让我们来回顾一下我们分析的流程:先对页面功能进行了分析,然后又分析了数据模型,最后又对view的功能和代码进行了详解。你是不是觉得这个分析里面少了点什么?没错了,就知道经验丰富的你已经看出来了,这里面少了对于流程的分析。
所以从我的分析中可以看的出来,我是先对各个原材料进行分析,然后再整体的分析(当然前提是我是理解流程的),这并不是分析代码的唯一方法,有时我也会采用跟着流程分析代码的方法。当然还有很多其他的分析方法,大家都是自己的套路嘛。
下面简单的说说流程分析的方法。记得多年前在学vb的时候,分析一个完整项目代码的时候,习惯从程序的入口点开始分析。虽然web网站和桌面软件的实现不同,但是大致思路是一样的(同时也有网站即软件的说法,在RESTful架构中)。所以我们要先找到网站的入口点所在。
和桌面应用项目的分析一样,网站的入口点就在于网页加载的时候。对于todos,自然就是加载所有的任务。所以对应着我们就可以发现这段代码
首先是对AppView的一个实例化:
var App = new AppView;
实例化,自然就会调用构造函数:
//在初始化过程中,绑定事件到Todos上,当任务列表改变时会触发对应的事件。最后把存在localStorage中的数据取出来。 initialize: function() { //下面这个是underscore库中的方法,用来绑定方法到目前的这个对象中,是为了在以后运行环境中调用当前对象的时候能够找到对象中的这些方法。 _.bindAll(this, 'addOne', 'addAll', 'render', 'toggleAllComplete'); this.input = this.$("#new-todo"); this.allCheckbox = this.$(".mark-all-done")[0]; Todos.bind('add', this.addOne); Todos.bind('reset', this.addAll); Todos.bind('all', this.render); Todos.fetch(); },
注意其中的Todos.fetch()方法,前面说过,这个项目是在客户端保存数据,所以使用fetch方法并不会发送请求到服务器。另外在前面关于collection的单独讲解中我们也知道了collection中调用fetch方法之后就会触发reset这个方法。所以现在流程走向reset——>addAll这个方法。
来看addAll这个方法:
//添加一个任务到页面id为todo-list的div/ul中 addOne: function(todo) { var view = new TodoView({model: todo}); this.$("#todo-list").append(view.render().el); }, // 把Todos中的所有数据渲染到页面,页面加载的时候用到 addAll: function() { Todos.each(this.addOne); },
在addAll中调用addOne方法,关于Todos.each很好理解,就是语法糖(简化的for循环),到此,加载页面的整个流程也就完成了。关于addOne方法的细节下面介绍。
然后再来看添加任务的流程,一个良好的代码命名风格始终是让人满心欢喜的。因为很显然,添加一个任务,自然就是addOne,其实你看events中的绑定也能知道,先看一下绑定:
// 绑定dom节点上的事件 events: { "keypress #new-todo": "createOnEnter", "keyup #new-todo": "showTooltip", "click .todo-clear a": "clearCompleted", "click .mark-all-done": "toggleAllComplete" },
这里并没有addOne方法的绑定,但是却有createOnEnter,语意其实一样的,另外这里其实要说下关于showTooltip这个方法,在任务输入框中,按键弹起的时候执行这个方法,具体代码有详细的注释了,这里不多介绍。
来看主线,createOnEnter这个方法:
//创建一个任务的方法,使用backbone.collection的create方法。将数据保存到localStorage,这是一个html5的js库。需要浏览器支持html5才能用。 createOnEnter: function(e) { if (e.keyCode != 13) return; Todos.create(this.newAttributes()); //创建一个对象之后会在backbone中动态调用Todos的add方法,该方法已绑定addOne。 this.input.val(''); },
注释已写明,Todos.create会调用addOne这个方法。由此顺理成章的来到addOne里面:
//添加一个任务到页面id为todo-list的div/ul中 addOne: function(todo) { var view = new TodoView({model: todo}); this.$("#todo-list").append(view.render().el); },
在里面实例化了一个TodoView类,前面我们说过,这个类是主管各个任务的显示的。具体代码就不细说了。
有了添加再来看更新,关于单个任务的操作,我们直接找TodoView就ok了。所以直接找到
// The DOM events specific to an item. events: { "click .check" : "toggleDone", "dblclick label.todo-content" : "edit", "click span.todo-destroy" : "clear", "keypress .todo-input" : "updateOnEnter", "blur .todo-input" : "close" },
其中的edit事件的绑定就是更新的一个开头,而updateOnEnter就是更新的具体动作。所以只要搞清楚这俩方法的作用一切就明了了。这里同样不用细说。
在往后还有删除一条记录以及清楚已有记录的功能,根据上面的分析过程,我想大家都很容易的去‘顺藤模瓜’。
关于Todos的分析到此就算完成了,我注释过的整个代码在github上:https://github.com/the5fire/the5fire-todos,供大家参考。
(此文章为转载)