1

コレクション内に重複チェックがあり、追加機能をオーバーライドしていますが、ページが更新されるまで機能しているようです。

重複は、「この項目は既に todo リストに追加されています!」というアラートでブロックされます。しかし、ページが更新されると、どちらの方法でも複製が 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();

さらに情報が必要な場合は、喜んで提供します。ありがとう!

4

1 に答える 1

1

Backbone では、create を呼び出すと、add と save の両方が呼び出されます。ここでソースを読んでください: http://backbonejs.org/docs/backbone.html#section-113

したがって、追加が行われないようにブロックしましたが、重複を追加するときに保存が行われました。

バックボーンの組み込みの検証を使用して、実行しようとしていたことを達成できます。

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;
    });
  }
});

ところで、バックボーンは古くなっているため、サイトのドキュメントにはコードでできることが反映されていません。

于 2014-12-11T05:54:23.573 に答える