Backbone Collection communicating with Backbone Models
I'm trying to understand what the best practice is for communicating between the different components of a Backbone project. I've been re-implementing the Backbone version of TodoMVC and my question is around removing models from the collection object.
I understand that Backbone model instances trigger a change event whenever any of its model properties are modified via .set()
and that the view associated with the model instance should .listenTo()
changes from the model instance and then re-render. However, what's the best practice for communication between models and the collection object that houses it? For example, how should the communication work when a model is removed from the collection object?
Here's what I think: when a model is removed, I think the model instance should emit a custom event that the collection object is listening for and pass itself along. When the collection object hears this event, it should remove the model instance from the list (along with any event listeners attached to the model) and then the entire collection object should re-render itself. This re-rendering process will then create a new set of models and model-views.
Is this the best approach? I would love to hear your input! To me, this process of re-rendering sounds really expensive since you'll have to destroy the existing DOM elements, remove their event listeners, and then re-create them again.
UPDATE - 3/26/2015
To make this more concrete, I'll include the code that I have so far and point out where I feel my understanding is off.
File Structure
collections
a. todoList.coffee
models
a. todo.coffee
views
a. todoView.coffee
b. todoListView.coffee
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
Explanation of Code
As you can see in my comments above, whenever a click happens on the remove button, my todoView triggers a custom event 'remove-todo'. The todoList collection listens to this event and removes the specific model from the collection. Since a 'remove' event is triggered whenever a collection removes a model, the todoListView listens for this 'remove' event and then re-renders. I feel like I'm off somewhere. Any advice?
It seems you are talking about views when you talk about models. When a model is removed from a collection you don't need a custom event, a "remove" event is triggered. http://backbonejs.org/#Collection-remove
If you want to remove the corresponding view, use http://backbonejs.org/#View-remove this will manage the DOM and listener.
The re-rendering of view (I don't understand what you are talking about when you talk about rerendering collection) can be triggered if you listen to "remove" models from the collection, otherwise listen to http://backbonejs.org/#Collection-add, or http://backbonejs.org/#Model-hasChanged is you want to rerender your view when a model has changed.
I hope it helps.
链接地址: http://www.djcxy.com/p/65536.html上一篇: 防止骨干收集重置
下一篇: 骨干集合与主干模型进行通信