我试图了解在Backbone项目的不同组件之间进行通信的最佳实践。我一直在重新实现TodoMVC的Backbone版本,我的问题是从集合对象中删除模型。
我了解Backbone模型实例在通过.set()
修改任何模型属性时触发更改事件,并且与模型实例关联的视图应该.listenTo()
从模型实例更改然后重新生成-render。但是,模型与收集它的集合对象之间进行通信的最佳实践是什么?例如,从集合对象中删除模型时,通信应该如何工作?
这就是我的想法:当一个模型被删除时,我认为模型实例应该发出一个集合对象正在监听并自行传递的自定义事件。当集合对象听到此事件时,它应该从列表中删除模型实例(以及附加到模型的任何事件侦听器),然后整个集合对象应该重新呈现自身。然后,这个重新渲染过程将创建一组新的模型和模型视图。
这是最好的方法吗?我很想听听你的意见!对我来说,这个重新渲染的过程非常昂贵,因为你必须销毁现有的DOM元素,删除它们的事件监听器,然后再重新创建它们。
更新 - 2015年3月26日
为了使这个更具体,我将包含我到目前为止的代码,并指出我觉得我的理解已经消失。
文件结构
集合
一个。 todoList.coffee
模型
一个。 todo.coffee
视图
一个。 todoView.coffee
湾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
代码说明
正如您在上面的评论中所看到的,只要在删除按钮上发生单击,我的todoView就会触发自定义事件'remove-todo'。 todoList集合侦听此事件并从集合中删除特定模型。由于每当集合删除模型时都会触发“删除”事件,因此todoListView会侦听此“删除”事件,然后重新呈现。我觉得我离开了某个地方。 有什么建议吗?
答案 0 :(得分:2)
当你谈论模特时,你似乎在谈论观点。从集合中删除模型时,您不需要自定义事件,即可删除"删除"事件被触发。 http://backbonejs.org/#Collection-remove
如果要删除相应的视图,请使用http://backbonejs.org/#View-remove这将管理DOM和侦听器。
如果您聆听"删除"重新呈现视图(我不会理解您在谈论重新呈现收集时所说的内容)。来自集合的模型,否则听取http://backbonejs.org/#Collection-add或http://backbonejs.org/#Model-hasChanged是否要在模型发生变化时重新渲染视图。
我希望它有所帮助。