Backbone.js之Todo源码浅析

相信每个接触了解过backbone的人都知道todo,网上的关于它的分析教程也都分析乱了。但是,知识只有自己学习领悟才是自己的,话不多说,正文开始。

在分析todo的源码之前,首先我们要知道todo具有哪些功能。todo类似于备忘录一样,其界面如下图:

1.当我们在输入框完成输入item时,按下enter键,下方会出现输入的内容item,item是一个li。

2.在所有item的最上面是一个全选checkbox。

3.每一个item是一个checkbox,当勾选任一行item时,则该行的内容会被删除线划掉,同时最下面的item left-1,Clear completed item+1。

4.当鼠标移到item上时,item的末端会出现一个删除符号,点击删除符号,该item即被删除。

简短介绍完todo的基本功能后,开始源码之旅。

todo.js整体长这个样子,如下图:

一个model,一个collection,两个view。

model详见如下:

 1   var Todo = Backbone.Model.extend({
 2     defaults: function() {
 3       return {
 4         title: "empty todo...",
 5         order: Todos.nextOrder(),
 6         done: false
 7       };
 8     },
 9     toggle: function() {
10       this.save({done: !this.get("done")});
11     }
12   });
View Code

默认设置defaults,返回一个list;定义了一个toggle,该触发器会设置保存model的状态。

collection详见如下:

 1  var TodoList = Backbone.Collection.extend({
 2     model: Todo,
 3     localStorage: new Backbone.LocalStorage("todos-backbone"),
 4     done: function() {
 5       return this.where({done: true});
 6     },
 7     remaining: function() {
 8       return this.where({done: false});
 9     },
10     nextOrder: function() {
11       if (!this.length) return 1;
12       return this.last().get('order') + 1;
13     },
14     comparator: 'order'
15   });
View Code

指定集合TodoList的mode为Todo,存储方式为localStorage,同时定义了done,remaining,nextOrder三个函数,最后指定了todo的排列顺序。

TodoView详见如下:

 1  var TodoView = Backbone.View.extend({
 2     tagName:  "li",
 3     template: _.template($('#item-template').html()),
 4     events: {
 5       "click .toggle"   : "toggleDone",
 6       "dblclick .view"  : "edit",
 7       "click a.destroy" : "clear",
 8       "keypress .edit"  : "updateOnEnter",
 9       "blur .edit"      : "close"
10     },
11     initialize: function() {
12       this.listenTo(this.model, 'change', this.render);
13       this.listenTo(this.model, 'destroy', this.remove);
14     },
15     render: function() {
16       this.$el.html(this.template(this.model.toJSON()));
17       this.$el.toggleClass('done', this.model.get('done'));
18       this.input = this.$('.edit');
19       return this;
20     },
21     toggleDone: function() {
22       this.model.toggle();
23     },
24     edit: function() {
25       this.$el.addClass("editing");
26       this.input.focus();
27     },
28     close: function() {
29       var value = this.input.val();
30       if (!value) {
31         this.clear();
32       } else {
33         this.model.save({title: value});
34         this.$el.removeClass("editing");
35       }
36     },
37     updateOnEnter: function(e) {
38       if (e.keyCode == 13) this.close();
39     },
40     clear: function() {
41       this.model.destroy();
42     }
43   });
View Code

AppView详见如下:

 1  var AppView = Backbone.View.extend({
 2     el: $("#todoapp"),
 3     statsTemplate: _.template($('#stats-template').html()),
 4     events: {
 5       "keypress #new-todo":  "createOnEnter",
 6       "click #clear-completed": "clearCompleted",
 7       "click #toggle-all": "toggleAllComplete"
 8     },
 9     initialize: function() {
10       this.input = this.$("#new-todo");
11       this.allCheckbox = this.$("#toggle-all")[0];
12       this.listenTo(Todos, 'add', this.addOne);
13       this.listenTo(Todos, 'reset', this.addAll);
14       this.listenTo(Todos, 'all', this.render);
15       this.footer = this.$('footer');
16       this.main = $('#main');
17       Todos.fetch();
18     },
19     render: function() {
20       var done = Todos.done().length;
21       var remaining = Todos.remaining().length;
22       if (Todos.length) {
23         this.main.show();
24         this.footer.show();
25         this.footer.html(this.statsTemplate({done: done, remaining: remaining}));
26       } else {
27         this.main.hide();
28         this.footer.hide();
29       }
30       this.allCheckbox.checked = !remaining;
31     },
32     addOne: function(todo) {
33       var view = new TodoView({model: todo});
34       this.$("#todo-list").append(view.render().el);
35     },
36     addAll: function() {
37       Todos.each(this.addOne, this);
38     },
39     createOnEnter: function(e) {
40       if (e.keyCode != 13) return;
41       if (!this.input.val()) return;
42       Todos.create({title: this.input.val()});
43       this.input.val('');
44     },
45     clearCompleted: function() {
46       _.invoke(Todos.done(), 'destroy');
47       return false;
48     },
49     toggleAllComplete: function () {
50       var done = this.allCheckbox.checked;
51       Todos.each(function (todo) { todo.save({'done': done}); });
52     }
53   });
View Code

 

posted @ 2017-10-07 13:41  Jinus  阅读(248)  评论(0编辑  收藏  举报