Backbone官方案例Todos分析


$(function(){
  //Model模塊
  var Todo = Backbone.Model.extend({
    //默認值,初始化字段
    defaults: function() {
      return {
        title: "empty todo...",
        order: Todos.nextOrder(),
        done: false
      };
    },
    //  將任務完成的狀態設置爲相反狀態
    toggle: function() {
      this.save({
        done: !this.get("done")
      });
    }

  });

  //Collection模塊
  var TodoList = Backbone.Collection.extend({
    //Collection的模型名稱爲todo
    model: Todo,
      //把todo-backbone儲存到本地
    localStorage: new Backbone.LocalStorage("todos-backbone"),
      //獲取已經完成任務的
    done: function() {
      return this.where({done: true});
    },
      //獲取沒有完成任務的
    remaining: function() {
      return this.where({done: false});
    },
      //獲取下一個插入的編號
    nextOrder: function() {
      if (!this.length) return 1;
      return this.last().get('order') + 1;
    },
      //內置函數,用於給backbone排序,參數是以order排序
    comparator: 'order'

  });
  var Todos = new TodoList;

  //View模塊
  //Dom節點的綁定、插入等操作
  var TodoView = Backbone.View.extend({
    //把template模板中獲取到的html代碼放在這個標籤之中
    tagName:  "li",
    //  設置對應模板
    template: _.template($('#item-template').html()),
    //  綁定事件
    events: {
      "click .toggle"   : "toggleDone",
      "dblclick .view"  : "edit",
      "click a.destroy" : "clear",
      "keypress .edit"  : "updateOnEnter",
      "blur .edit"      : "close"
    },
    //  初始化函數,設置對model的監聽,用戶view之間的通信
    initialize: function() {
      this.listenTo(this.model, 'change', this.render);
      this.listenTo(this.model, 'destroy', this.remove);
    },
    //渲染函數,用戶渲染數據到模板中,設置一些全局函數
    render: function() {
      this.$el.html(this.template(this.model.toJSON()));
      this.$el.toggleClass('done', this.model.get('done'));
      this.input = this.$('.edit');
      return this;
    },
    //  控制任務完成或者未完成
    toggleDone: function() {
      this.model.toggle();
    },
    //修改編輯任務時的樣式
    edit: function() {
      this.$el.addClass("editing");
      this.input.focus();
    },
    //關閉編輯,並把修改內容同步到界面
    close: function() {
      var value = this.input.val();
      if (!value) {
        this.clear();
      } else {
        this.model.save({title: value});
        this.$el.removeClass("editing");
      }
    },
    //按回車則編輯關閉
    updateOnEnter: function(e) {
      if (e.keyCode == 13) this.close();
    },
    //從local Storage中刪除一個條目
    clear: function() {
      this.model.destroy();
    }

  });
  //顯示所有任務列表,顯示完成多少、未完成多少的列表狀態以及任務的添加
  var AppView = Backbone.View.extend({

    //綁定頁面上的DOM節點
    el: $("#todoapp"),
    //統計數據模板
    statsTemplate: _.template($('#stats-template').html()),
    //  綁定事件
    events: {
      "keypress #new-todo":  "createOnEnter",
      "click #clear-completed": "clearCompleted",
      "click #toggle-all": "toggleAllComplete"
    },
    //包括事件的綁定以及數據的讀取,操作完成之後調用Todos.fetch()
    initialize: function() {
      this.input = this.$("#new-todo");
      this.allCheckbox = this.$("#toggle-all")[0];
      //監聽Collection,一有變動就會重新渲染,以達到實時交互的效果
      this.listenTo(Todos, 'add', this.addOne);
      this.listenTo(Todos, 'reset', this.addAll);
      this.listenTo(Todos, 'all', this.render);

      this.footer = this.$('footer');
      this.main = $('#main');
      //會將數據同步到服務器端→local storage,然後調用了reset方法
      //  而reset綁定了addAll,接下來調用addAll
      //  addAll調用了addOne,在addOne裏面實例化了TodoView,而這個類就是主要用數據的同步然後顯示的
      //  addOne裏面初始化了render事件,一旦model改變就立刻調用render進行重繪
      Todos.fetch();
    },

    //更新當前任務列表的狀態
    render: function() {
      var done = Todos.done().length;
      var remaining = Todos.remaining().length;

      if (Todos.length) {
        this.main.show();
        this.footer.show();
        this.footer.html(this.statsTemplate({done: done, remaining: remaining}));
      } else {
        this.main.hide();
        this.footer.hide();
      }
      //根據剩餘多少未完成確定標記全部完成的checkbox的顯示
      this.allCheckbox.checked = !remaining;
    },

    //添加一個任務到頁面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, this);
    },

    //創建任務,將數據保存到local Storage中
    createOnEnter: function(e) {
      if (e.keyCode != 13) return;
      if (!this.input.val()) return;
      //創建一個對象之後會動態調用Todos的add方法,該方法綁定addOne
      Todos.create({title: this.input.val()});
      this.input.val('');
    },

    //去掉所有已完成的任務
    clearCompleted: function() {
      _.invoke(Todos.done(), 'destroy');
      return false;
    },
    //處理頁面點擊標記全部完成按鈕
    toggleAllComplete: function () {
      var done = this.allCheckbox.checked;
      Todos.each(function (todo) { todo.save({'done': done}); });
    }

  });

  //網頁加載的入口,實例化之後會調用構造函數initialize,以及綁定事件到todo上
  var App = new AppView;

});
發佈了44 篇原創文章 · 獲贊 28 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章