• 跳转到… +
    examples/backbone.localStorage.js examples/todos/todos.js
  • todos.js

  • §

    由 Jérôme Gravel-Niquet 贡献的 Backbone 示例应用程序。此演示使用简单的 LocalStorage 适配器 在浏览器中持久化 Backbone 模型。

  • §

    DOM 准备就绪后加载应用程序,使用 jQuery.ready

    $(function(){
  • §

    Todo 模型

  • §
  • §

    我们的基本 Todo 模型具有 title、order 和 done 属性。

      var Todo = Backbone.Model.extend({
  • §

    Todo 项目的默认属性。

        defaults: function() {
          return {
            title: "empty todo...",
            order: Todos.nextOrder(),
            done: false
          };
        },
  • §

    切换此 Todo 项目的 done 状态。

        toggle: function() {
          this.save({done: !this.get("done")});
        }
    
      });
  • §

    Todo 集合

  • §
  • §

    Todo 集合由 localStorage 支持,而不是远程服务器。

      var TodoList = Backbone.Collection.extend({
  • §

    对该集合模型的引用。

        model: Todo,
  • §

    将所有 Todo 项目保存在 "todos-backbone" 命名空间下。

        localStorage: new Backbone.LocalStorage("todos-backbone"),
  • §

    筛选所有已完成的 Todo 项目列表。

        done: function() {
          return this.where({done: true});
        },
  • §

    筛选列表,仅显示尚未完成的 Todo 项目。

        remaining: function() {
          return this.where({done: false});
        },
  • §

    我们按顺序保存 Todo,尽管它们在数据库中按无序 GUID 保存。这会为新项目生成下一个顺序号。

        nextOrder: function() {
          if (!this.length) return 1;
          return this.last().get('order') + 1;
        },
  • §

    Todo 按其原始插入顺序排序。

        comparator: 'order'
    
      });
  • §

    创建我们的全局 Todos 集合。

      var Todos = new TodoList;
  • §

    Todo 项目视图

  • §
  • §

    Todo 项目的 DOM 元素…

      var TodoView = Backbone.View.extend({
  • §

    … 是一个列表标签。

        tagName:  "li",
  • §

    缓存单个项目的模板函数。

        template: _.template($('#item-template').html()),
  • §

    特定于项目的 DOM 事件。

        events: {
          "click .toggle"   : "toggleDone",
          "dblclick .view"  : "edit",
          "click a.destroy" : "clear",
          "keypress .edit"  : "updateOnEnter",
          "blur .edit"      : "close"
        },
  • §

    TodoView 监听其模型的变化,重新渲染。由于此应用程序中 Todo 和 TodoView 之间存在一对一对应关系,因此为了方便起见,我们在模型上设置了直接引用。

        initialize: function() {
          this.listenTo(this.model, 'change', this.render);
          this.listenTo(this.model, 'destroy', this.remove);
        },
  • §

    重新渲染 Todo 项目的标题。

        render: function() {
          this.$el.html(this.template(this.model.toJSON()));
          this.$el.toggleClass('done', this.model.get('done'));
          this.input = this.$('.edit');
          return this;
        },
  • §

    切换模型的 "done" 状态。

        toggleDone: function() {
          this.model.toggle();
        },
  • §

    将此视图切换到 "editing" 模式,显示输入字段。

        edit: function() {
          this.$el.addClass("editing");
          this.input.focus();
        },
  • §

    关闭 "editing" 模式,保存对 Todo 的更改。

        close: function() {
          var value = this.input.val();
          if (!value) {
            this.clear();
          } else {
            this.model.save({title: value});
            this.$el.removeClass("editing");
          }
        },
  • §

    如果按 enter 键,则表示已完成编辑项目。

        updateOnEnter: function(e) {
          if (e.keyCode == 13) this.close();
        },
  • §

    删除项目,销毁模型。

        clear: function() {
          this.model.destroy();
        }
    
      });
  • §

    应用程序

  • §
  • §

    我们的整体 AppView 是 UI 的顶层部分。

      var AppView = Backbone.View.extend({
  • §

    不生成新元素,而是绑定到 HTML 中已存在的应用程序骨架。

        el: $("#todoapp"),
  • §

    应用程序底部统计行模板。

        statsTemplate: _.template($('#stats-template').html()),
  • §

    用于创建新项目和清除已完成项目的委托事件。

        events: {
          "keypress #new-todo":  "createOnEnter",
          "click #clear-completed": "clearCompleted",
          "click #toggle-all": "toggleAllComplete"
        },
  • §

    在初始化时,我们绑定到 Todos 集合上的相关事件,当项目添加或更改时。通过加载可能保存在 localStorage 中的任何预先存在的 Todo 来启动操作。

        initialize: function() {
    
          this.input = this.$("#new-todo");
          this.allCheckbox = this.$("#toggle-all")[0];
    
          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');
    
          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();
          }
    
          this.allCheckbox.checked = !remaining;
        },
  • §

    通过为其创建视图并将元素附加到 <ul> 中,将单个 Todo 项目添加到列表中。

        addOne: function(todo) {
          var view = new TodoView({model: todo});
          this.$("#todo-list").append(view.render().el);
        },
  • §

    一次性添加 Todos 集合中的所有项目。

        addAll: function() {
          Todos.each(this.addOne, this);
        },
  • §

    如果在主输入字段中按回车键,则创建新的 Todo 模型,并将其持久化到 localStorage。

        createOnEnter: function(e) {
          if (e.keyCode != 13) return;
          if (!this.input.val()) return;
    
          Todos.create({title: this.input.val()});
          this.input.val('');
        },
  • §

    清除所有已完成的 Todo 项目,销毁其模型。

        clearCompleted: function() {
          _.invoke(Todos.done(), 'destroy');
          return false;
        },
    
        toggleAllComplete: function () {
          var done = this.allCheckbox.checked;
          Todos.each(function (todo) { todo.save({'done': done}); });
        }
    
      });
  • §

    最后,我们通过创建 App 来启动操作。

      var App = new AppView;
    
    });