Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/backbone.js/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 与主干模型通信的主干集合_Javascript_Backbone.js_Backbone Views_Backbone Model_Backbone.js Collections - Fatal编程技术网

Javascript 与主干模型通信的主干集合

Javascript 与主干模型通信的主干集合,javascript,backbone.js,backbone-views,backbone-model,backbone.js-collections,Javascript,Backbone.js,Backbone Views,Backbone Model,Backbone.js Collections,我试图了解在主干项目的不同组件之间进行通信的最佳实践是什么。我一直在重新实现的主干版本,我的问题是从集合对象中删除模型 我了解,只要通过.set()修改主干模型实例的任何模型属性,主干模型实例就会触发更改事件,并且与模型实例关联的视图应该.listenTo()从模型实例更改,然后重新渲染。但是,在模型和容纳它的集合对象之间进行通信的最佳实践是什么?例如,从集合对象中删除模型时,通信应如何工作? 以下是我的想法:当删除模型时,我认为模型实例应该发出一个集合对象正在侦听的自定义事件,并传递它自己。当

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

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

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

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

更新-2015年3月26日

为了使这更具体,我将包含到目前为止的代码,并指出我认为我的理解有偏差的地方

文件结构

  • 收藏

    a。托多利斯特咖啡

  • 模型

    a。托多咖啡

  • 观点

    a。咖啡

    b。todoListView.咖啡

  • 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
    
    window.app = app = window.app || {}
    
    app.Todo = Backbone.Model.extend
      defaults:
        title: ''
        completed: false
    
      toggleComplete: ->
        this.set 'completed', !this.get 'completed'
    
    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
    
    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
    
    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
    
    待办事项咖啡

    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
    
    window.app = app = window.app || {}
    
    app.Todo = Backbone.Model.extend
      defaults:
        title: ''
        completed: false
    
      toggleComplete: ->
        this.set 'completed', !this.get 'completed'
    
    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
    
    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
    
    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
    
    托多利斯特咖啡店

    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
    
    window.app = app = window.app || {}
    
    app.Todo = Backbone.Model.extend
      defaults:
        title: ''
        completed: false
    
      toggleComplete: ->
        this.set 'completed', !this.get 'completed'
    
    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
    
    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
    
    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
    
    提供咖啡

    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
    
    window.app = app = window.app || {}
    
    app.Todo = Backbone.Model.extend
      defaults:
        title: ''
        completed: false
    
      toggleComplete: ->
        this.set 'completed', !this.get 'completed'
    
    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
    
    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
    
    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
    
    todoListView.咖啡

    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
    
    window.app = app = window.app || {}
    
    app.Todo = Backbone.Model.extend
      defaults:
        title: ''
        completed: false
    
      toggleComplete: ->
        this.set 'completed', !this.get 'completed'
    
    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
    
    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
    
    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
    
    代码说明

    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
    
    window.app = app = window.app || {}
    
    app.Todo = Backbone.Model.extend
      defaults:
        title: ''
        completed: false
    
      toggleComplete: ->
        this.set 'completed', !this.get 'completed'
    
    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
    
    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
    
    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会侦听此“删除”事件,然后重新渲染。我觉得我要离开某个地方了有什么建议吗?

    当你谈论模型时,你似乎在谈论视图。从不需要自定义事件的集合中删除模型时,将触发“删除”事件。

    如果要删除相应的视图,请使用它来管理DOM和侦听器

    如果您从集合中侦听“删除”模型,或者侦听,或者您希望在模型更改时重新渲染视图,则可能会触发视图的重新渲染(我不理解您在谈论重新渲染集合时谈论的是什么)


    我希望有帮助

    集合所做的是包含模型,如果需要,可以在添加/删除模型或替换(重置)所有模型时执行排序,只要使用主干方法在集合中添加/删除/重置模型,这些事件就会自动生成。不用担心,我觉得这个逻辑不错