【问题标题】:Make Backbone.js items within localStorage unique?使 localStorage 中的 Backbone.js 项目独一无二?
【发布时间】:2015-02-09 10:03:05
【问题描述】:

我的收藏中有一个重复检查,我在其中覆盖了 add 函数,它似乎在页面刷新之前有效。

重复项被阻止并显示“您已将此项目添加到待办事项列表!”的警告。但似乎当页面刷新时,无论哪种方式,副本都会添加到 localStorage 中。很想找到这个问题的解决方案——过去几天我一直在为这个问题摸不着头脑。

我的收藏如下:

app.TodoList = Backbone.Collection.extend({
  model: app.Todo,
  localStorage: new Store("backbone-todo"),
  completed: function() {
    return this.filter(function(todo){
      return todo.get('completed');
    });
  },
  remaining: function(){
    return this.without.apply(this, this.completed());
  }
});

app.TodoList.prototype.add = function(todo) {

var isDupe = this.any(function(_todo){ return _todo.get('title').toLowerCase() === todo.get('title').toLowerCase();
});

return isDupe ? alert("You've already added this item to the todo list!") : Backbone.Collection.prototype.add.call(this, todo);}


// instance of the Collection
app.todoList = new app.TodoList();

这是模型:

  app.Todo = Backbone.Model.extend({
  defaults: {
    title: '',
    completed: false
  },
  toggle: function(){
    this.save({ completed: !this.get('completed')});
  }
});

观点:

  app.TodoView = Backbone.View.extend({
  tagName: 'li',
  template: _.template($('#item-template').html()),
  render: function(){
    this.$el.html(this.template(this.model.toJSON()));
    this.input = this.$('.edit');
    return this; // enable chained calls
  },
  initialize: function(){
    this.model.on('change', this.render, this);
    this.model.on('destroy', this.remove, this); // remove: 'Convenience Backbone'
  },
  events: {
    'dblclick label' : 'edit',
    'keypress .edit' : 'updateOnEnter',
    'blur .edit' : 'close',
    'click .toggle' : 'toggleCompleted',
    'click .destroy' : 'destroy'
  },
  edit: function(){
    this.$el.addClass('editing');
    this.input.focus();
  },
  close: function(){
   var value = this.input.val().trim();
   if(value) {
    this.model.save({ title: value });
   }
   this.$el.removeClass('editing');
  },
  updateOnEnter: function(e){
    if(e.which == 13){
      this.close();
    }
  },
  toggleCompleted: function(){
    this.model.toggle();
  },
  destroy: function(){
    this.model.destroy();
  }
});

// renders the full list of todo items calling TodoView for each one.
app.AppView = Backbone.View.extend({
  el: '#todoapp',
  initialize: function () {
    this.input = this.$('#new-todo');
    app.todoList.on('add', this.addAll, this);
    app.todoList.on('reset', this.addAll, this);
    app.todoList.fetch(); // Loads list from local storage
  },
  events: {
    'keypress #new-todo': 'createTodoOnEnter'
  },
  createTodoOnEnter: function(e){
    if ( e.which !== 13 || !this.input.val().trim() ) { // ENTER_KEY = 13
      return;
    }
    app.todoList.create(this.newAttributes());
    this.input.val(''); // clean input box
  },
  addOne: function(todo){
    var view = new app.TodoView({model: todo});

    $('#todo-list').append(view.
      render().el);

  },
  addAll: function(){
    this.$('#todo-list').html(''); // clean the todo list
    // filter todo item list
    switch(window, filter){
      case 'pending':
          _.each(app.todoList.remaining(), this.addOne);
          break;
        case 'completed':
          _.each(app.todoList.completed(), this.addOne);
          break;
        default:
          app.todoList.each(this.addOne, this);
          break;
    }
  },
  newAttributes: function(){
    return {
      title: this.input.val().trim(),
      completed: false
    }
  }
});

路由器:

app.Router = Backbone.Router.extend({
  routes: {
    '*filter' : 'setFilter'
  },
  setFilter: function(params){
    console.log('app.router.params = ' + params);
    window.filter = params.trim() || '';
    app.todoList.trigger('reset');
  }
})

还有初始化器:

 app.router = new app.Router();
 Backbone.history.start();
 app.appView = new app.AppView();

如果需要更多信息,我们很乐意提供。谢谢!

【问题讨论】:

    标签: javascript backbone.js backbone-local-storage


    【解决方案1】:

    在 Backbone 中,当您调用 create 时,会同时调用 add 和 save。在此处阅读源代码:http://backbonejs.org/docs/backbone.html#section-113

    所以你阻止了添加的发生,但添加副本时保存仍然发生。

    您可以使用 Backbone 的内置验证来完成您想要做的事情:

    app.Todo = Backbone.Model.extend({
      defaults: {
        title: '',
        completed: false
      },
      initialize: function() {
        this.on('error', function(model, error) {
          alert(error);
        });
      },
      toggle: function(){
        this.save({ completed: !this.get('completed')});
      },
      validate: function(attrs, options) {
        if ( this.collection.isExistingTodoTitleOnOtherTodo(attrs) ) {
          return "You've already added this item to the todo list!";
        }
      }
    });
    
    app.TodoList = Backbone.Collection.extend({
      model: app.Todo,
      localStorage: new Store("backbone-todo"),
      completed: function() {
        return this.filter(function(todo){
          return todo.get('completed');
        });
      },
      remaining: function(){
        return this.without.apply(this, this.completed());
      },
      isExistingTodoTitleOnOtherTodo: function(attrs) {
        return this.any(function(todo) {
          var titleMatch = todo.get('title').toLowerCase() === attrs.title.toLowerCase();
          var idMatch = attrs.id === todo.id;
    
          return titleMatch && !idMatch;
        });
      }
    });
    

    顺便说一句,您的 Backbone 已过时,因此网站上的文档无法反映您可以在代码中执行的操作。

    【讨论】:

      猜你喜欢
      • 2023-03-06
      • 2012-06-22
      • 2013-02-24
      • 1970-01-01
      • 2011-09-27
      • 2013-12-24
      • 1970-01-01
      • 2012-05-19
      • 2014-04-18
      相关资源
      最近更新 更多