骨干集合与主干模型进行通信

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

我了解,Backbone模型实例通过.set()修改其任何模型属性时会触发更改事件,并且与模型实例关联的视图应该从.listenTo()更改模型实例并重新呈现。 但是,模型和收集对象之间的通信的最佳实践是什么? 例如, 从收集对象中删除模型时,通信应如何工作?

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

这是最好的方法吗? 我很想听听你的意见! 对我来说,这个重新渲染的过程听起来非常昂贵,因为你必须销毁现有的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集合侦听此事件并从集合中删除特定模型。 由于每当集合删除模型时都会触发'remove'事件,因此todoListView将侦听此“删除”事件,然后重新呈现。 我觉得我离开了某个地方。 有什么建议?


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

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

    如果您听取集合中的“删除”模型,则可能会触发重新呈现视图(我不明白您在谈论重新渲染集合时所说的内容),否则请听http://backbonejs.org/。 #Collection-add或http://backbonejs.org/#Model-hasChanged是你想在模型改变时重新渲染你的视图。

    我希望它有帮助。

    链接地址: http://www.djcxy.com/p/65535.html

    上一篇: Backbone Collection communicating with Backbone Models

    下一篇: creating new entities in Backbone Marionette for related models