Связь Backbone Collection с моделями Backbone

Я пытаюсь понять, как лучше всего общаться между различными компонентами проекта Backbone. Я повторно реализовал Backbone-версию TodoMVC, и мой вопрос касается удаления моделей из объекта коллекции.

Я понимаю, что экземпляры модели Backbone инициируют событие изменения всякий раз, когда любое из его свойств модели изменяется с помощью .set(), и что представление, связанное с экземпляром модели, должно .listenTo() измениться по сравнению с экземпляром модели, а затем выполнить повторную визуализацию. Однако как лучше всего организовать связь между моделями и объектом коллекции, в котором они размещены? Например, как должна работать связь, когда модель удаляется из объекта коллекции?

Вот что я думаю: когда модель удаляется, я думаю, что экземпляр модели должен генерировать пользовательское событие, которое прослушивает объект коллекции, и передавать себя. Когда объект коллекции получает это событие, он должен удалить экземпляр модели из списка (вместе со всеми прослушивателями событий, прикрепленными к модели), а затем весь объект коллекции должен повторно отобразить себя. Этот процесс повторного рендеринга затем создаст новый набор моделей и представлений моделей.

Это лучший подход? Я хотел бы услышать ваш вклад! Для меня этот процесс повторного рендеринга кажется очень дорогим, поскольку вам придется уничтожить существующие элементы DOM, удалить их прослушиватели событий, а затем снова создать их заново.

ОБНОВЛЕНИЕ – 26 марта 2015 г.

Чтобы сделать это более конкретным, я включу код, который у меня есть до сих пор, и укажу, где, по моему мнению, я не понимаю.

Структура файла

  1. коллекции

    а. todoList.coffee

  2. модели

    а. todo.coffee

  3. взгляды

    а. todoView.coffee

    б. todoListView.coffee

  4. приложение.кофе

app.coffee

window.app = app = window.app || {} 

data = [
  {
    title: 'Eat dinner',
    completed: false
  }
  {
    title: 'Go to gym',
    completed: true
  }
]

app.todos = data.map (todo) -> new app.Todo todo

app.todoList = new app.TodoList app.todos

app.todoListView = new app.TodoListView
  collection: app.todoList

app.$app = $('#todo-app')

$('#todo-app').append app.todoListView.render().el

todo.coffee

window.app = app = window.app || {}

app.Todo = Backbone.Model.extend
  defaults:
    title: ''
    completed: false

  toggleComplete: ->
    this.set 'completed', !this.get 'completed'

todoList.coffee

window.app = app = window.app || {}

app.TodoList = Backbone.Collection.extend
  model: app.Todo

  initialize: () ->
    # This is what I don't like - creating 'remove-todo' event
    this.on 'remove-todo', this.removeTodoFromList

  removeTodoFromList: (model) ->
    this.remove model

  getCompleted: ->
    this.filter (model) -> model.completed

  getNotCompleted: ->
    this.filter (model) -> !model.completed

todoView.coffee

window.app = app = window.app || {}

app.TodoView = Backbone.View.extend
  tagName: 'li'

  events:
    'click input'   : 'checkComplete'
    'click .delete' : 'removeTodo'

  checkComplete: (e) ->
    this.model.toggleComplete()

  removeTodo: (e) ->
    # I don't like how the collection is listening for this custom event 'remove-todo'
    this.model.trigger 'remove-todo', this.model

  initialize: ->
    this.listenTo this.model, 'change:completed', () ->
      this.render()

  render: ->
    template = _.template $('#todo-view').html()
    this.$el.html template this.model.toJSON()
    return this

todoListView.coffee

window.app = app = window.app || {}

app.TodoListView = Backbone.View.extend
  tagName: 'ul'

  className: 'todo-list'

  initialize: ->
    this.collection.on 'remove', (() ->
      this.resetListView()
      this.render()
    ), this

  addOne: (model) ->
    todoView = new app.TodoView
      model: model

    this.$el.append todoView.render().el

  resetListView: ->
    this.$el.html('')

  render: ->
    _.each this.collection.models, ((model) -> this.addOne model), this
    return this

Объяснение кода

Как вы можете видеть в моих комментариях выше, всякий раз, когда происходит щелчок по кнопке удаления, мой todoView запускает пользовательское событие «удалить-todo». Коллекция todoList прослушивает это событие и удаляет конкретную модель из коллекции. Поскольку событие «удалить» запускается всякий раз, когда коллекция удаляет модель, todoListView прослушивает это событие «удаления», а затем выполняет повторную визуализацию. Я чувствую, что я где-то пропал. Есть совет?


comment
Что делает коллекция, так это содержит модели, и если вы хотите, сделайте что-то вроде сортировки, когда модель добавляется/удаляется или вся модель заменяется (сбрасывается), и пока вы используете метод магистрали для добавления/удаления/сброса моделей в коллекции, эти события генерируются автоматически. не нужно беспокоиться об этом.   -  person suish    schedule 26.03.2015
comment
эта логика мне кажется хорошей   -  person François Richard    schedule 31.03.2015


Ответы (1)


Кажется, вы говорите о представлениях, когда говорите о моделях. Когда модель удаляется из коллекции, вам не нужно специальное событие, запускается событие «удалить». http://backbonejs.org/#Collection-remove

Если вы хотите удалить соответствующее представление, используйте http://backbonejs.org/#View-remove. это будет управлять DOM и прослушивателем.

Повторный рендеринг представления (я не понимаю, о чем вы говорите, когда говорите о ререндеринге коллекции) может быть вызван, если вы слушаете «удалить» модели из коллекции, в противном случае слушайте http://backbonejs.org/#Collection-add или http://backbonejs.org/#Model-hasChanged, если вы хотите перерисовать свое представление при изменении модели.

Я надеюсь, что это помогает.

person François Richard    schedule 26.03.2015