Backbone 与 Backbone 个模型通信的集合

Backbone Collection communicating with Backbone Models

我试图了解在 Backbone 项目的不同组件之间进行通信的最佳做法是什么。我一直在重新实现 TodoMVC 的 Backbone 版本,我的问题是关于从集合对象中删除模型。

我了解 Backbone 模型实例在其任何模型属性通过 .set() 修改时触发更改事件,并且与模型实例关联的视图应 .listenTo() 从模型实例,然后重新渲染。但是,模型与容纳它的集合对象之间的最佳通信实践是什么?例如,当模型从集合对象中移除时,通信应该如何进行?

这是我的想法:删除模型时,我认为模型实例应该发出集合对象正在侦听的自定义事件并将其自身传递。当集合对象听到这个事件时,它应该从列表中删除模型实例(连同附加到模型的任何事件监听器),然后整个集合对象应该重新呈现自己。这个重新渲染过程将创建一组新的模型和模型视图。

这是最好的方法吗?我很想听听您的意见!对我来说,这个重新渲染的过程听起来非常昂贵,因为你必须销毁现有的 DOM 元素,删除它们的事件监听器,然后重新创建它们。

更新 - 2015 年 3 月 26 日

为了使这个更具体,我将包括我目前拥有的代码并指出我认为我的理解有误的地方。

文件结构

  1. 合集

    一个。 todoList.coffee

  2. 型号

    一个。 todo.coffee

  3. 观看次数

    一个。 todoView.coffee

    b。 todoListView.coffee

  4. app.coffee

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 就会触发一个自定义事件 'remove-todo'。 todoList 集合侦听此事件并从集合中删除特定模型。由于每当集合删除模型时都会触发 'remove' 事件,因此 todoListView 会侦听此 'remove' 事件,然后重新呈现。我觉得我离开了某个地方。 有什么建议吗?

当你谈论模型时,你似乎在谈论观点。当模型从集合中移除时,您不需要自定义事件,将触发 "remove" 事件。 http://backbonejs.org/#Collection-remove

如果要删除相应的视图,请使用 http://backbonejs.org/#View-remove 这将管理 DOM 和侦听器。

视图的重新渲染(你说重新渲染集合我不明白你在说什么)如果你从集合中收听"remove"个模型,就可以触发,否则听http://backbonejs.org/#Collection-add, or http://backbonejs.org/#Model-hasChanged 您想在模型更改时重新渲染视图吗?

希望对您有所帮助。