Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/418.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 - Fatal编程技术网

Javascript 如何在列表和项目视图中呈现主干集合?

Javascript 如何在列表和项目视图中呈现主干集合?,javascript,backbone.js,Javascript,Backbone.js,我在一个联系人栏上工作,它在html列表中呈现用户的所有联系人 我所拥有的: UserModel-这是一个简单的主干。带有用户名和电子邮件的模型 UserCollection-用作联系人列表 ContactsView-这是ul联系人列表 ContactView-这是渲染为li的单个联系人模型 我目前正在绞尽脑汁研究一种解决方案,即如何(以及在何处)获取我的UserCollection,以及如何将单个模型向下传递到单个ContactView项 具体障碍包括: 我应该在哪里提取、存储UserColl

我在一个联系人栏上工作,它在html列表中呈现用户的所有联系人

我所拥有的:

  • UserModel-这是一个简单的主干。带有用户名和电子邮件的模型
  • UserCollection-用作联系人列表
  • ContactsView-这是ul联系人列表
  • ContactView-这是渲染为li的单个联系人模型
  • 我目前正在绞尽脑汁研究一种解决方案,即如何(以及在何处)获取我的UserCollection,以及如何将单个模型向下传递到单个ContactView项

    具体障碍包括:

  • 我应该在哪里提取、存储UserCollection
  • 如何呈现联系人列表
  • 如何呈现联系人项目
  • 如何防止fetch({success:callback})破坏我的代码结构
  • 我目前的代码是:

    入口点:

    // create a new instance of the contact list view
    var view = new ContactsView();
    // insert the rendered element of the contact list view in to the dom
    $('div.contacts-body').html(view.render().el);
    view.fetch({ success: view.loadContacts });
    
    联系人视图:

    define(
        ['jquery', 'underscore', 'backbone', 'text!templates/conversations/contacts.html', 'collections/users', 'views/conversations/contact'],
        function($, _, Backbone, ContactsTemplate, UserCollection, ContactView) {
    
            var ContactsView = Backbone.View.extend({
    
                tagName: "ul",
    
                className: "contacts unstyled",
    
                attributes: "",
    
                // I am feeling uneasy hardcoding the collection into the view
                initialize: function() {
                    this.collection = new UserCollection();
                },
    
                // this renders our contact list
                // we don't need any template because we just have <ul class="contacts"></ul>
                render: function() {
                    this.$el.html();
                    return this;
                },
    
                // this should render the contact list
                // really crappy and unflexible
                loadContacts: function() {
                    this.collection.each(function(contact) {
                        // create a new contact item, insert the model
                        var view = new ContactView({ model: contact });
                        // append it to our list
                        this.$el.append(view.render().el);
                    });
                }
    
            });
    
            return ContactsView;
    
    });
    
    有人能帮我克服四个障碍吗

    欢迎提供好的示例链接。我将我的代码风格定位在todos列表中,不幸的是,todos列表没有那么高级

    更新代码:

    define(
        ['jquery', 'underscore', 'backbone', 'text!templates/conversations/contacts.html', 'collections/users', 'views/conversations/contact'],
        function($, _, Backbone, ContactsTemplate, UserCollection, ContactView) {
    
            var ContactsView = Backbone.View.extend({
    
                tagName: "ul",
    
                className: "contacts unstyled",
    
                attributes: "",
    
                events: {
    
                },
    
                initialize: function() {
                    this.collection = new UserCollection();
                    this.collection.on('reset', this.render);
                    this.collection.fetch();
                },
    
                render: function() {
                    // in chromium console
                    console.log(this.el); // first: html, second: undefined
                    console.log(this.$el); // first: html in array, second: undefined
                    this.$el.empty(); // error on the called that this.$el is undefined
    
                    this.collection.each(function(contact) {
                        var view = new ContactView({ model: contact });
                        this.$el.append(view.el);
                    }.bind(this));
    
                    return this;
                }
    
            });
    
            return ContactsView;
    

    重置是否会触发此.render两次?

    首先:为什么要获取视图?主干视图没有获取方法

    1获取UserCollection的正确位置应在视图的initialize方法中: 现在,您可以在需要时准确地获取联系人。下一步是呈现集合

    2绑定到重置事件会使loadContacts方法过时,我们可以在render函数中执行此操作: 现在,您可以在render方法中呈现联系人列表,应该在该方法中完成

    3 ContactView实际上看起来不错。 只需使该项在initialize方法中呈现自己,就不必在ContactsView的呈现方法中进行无用的调用,也不必将代码弄得乱七八糟。也都在这里

    initialize: function() { // ContactView
      _.bindAll(this, 'render', 'otherMethodName', ...);
      ...
      this.render(); // Render in the end of initialize
    }
    
    我不知道你在问什么,但我认为最好的方法是不要使用成功回调。无论何时对集合和模型执行操作,它们都会触发事件,因此利用它们比成功回调更健壮、更可靠。Christophe Coenraets的是这种listview listitemview排列的一个很好的例子

    希望这有帮助

    更新:添加了u.bindAlls以修复事件绑定渲染调用中的此问题

    注意:所有代码都经过简化,没有经过测试

    当我像您一样定义了所有的元素结构并实现了所有的模型、集合和视图之后,我实现了一个加载程序,它负责触发抓取和渲染操作

    首先,我需要从外部公开类定义,如下所示:

    // App.js
    var App = {}
    
    // ContactsCollection.js
    $(function(){
      var App.ContactsCollection = Backbone.Collection.extend({ ... });
    });
    
    // ContactsView.js
    $(function(){
      var App.ContactsView = Backbone.View.extend({ ... });
    });
    
    // and so on...
    
    然后我实现了我称之为加载器的东西:

    您必须做的另一个更改是配置
    ContactsView
    ,以响应
    App.contactsCollection
    中的更改,因为
    fetch()
    是异步的,所以在尚未加载集合时,您可以调用
    render()
    ,因此,您必须告诉CollectionView在集合准备就绪时自行渲染它:

    var ContactsView = Backbone.View.extend({
      initialize: function( opts ){
        this.collection.on( 'reset', this.addAll, this );
        this.collection.on( 'add', this.addOne, this );
        // ... same with 'remove'
      },
    
      addOne: function( model ){
        var view = new App.ContactView({ model: contact });
        this.$el.append( view.render().el );
      },
    
      addAll: function(){
        this.collection.each( $.proxy( this.addOne, this ) );
      }
    });
    
    您必须按照正确的顺序要求js文件:

  • App.js
  • 您的模型、集合、视图
  • AppLoad.js
  • 使用此系统,您可以获得:

    • 外部访问您的收藏,以防您需要从其他地方访问它
    • 使用的
      CollectionView.el
      的外部控制更适合于解耦和测试
    • CollectionView将自动响应集合中的更改

    注意:如果您使用
    路由器
    可以将
    AppLoad.js
    逻辑移动到那里。

    您好,谢谢您的帮助。这确实让我更清楚:)似乎有两个错误。1.)此。$el未定义2.)渲染将被调用两次。我用新的codeundefined更新了最初的帖子,它是由javascript作用域引起的,这导致它并不总是预期的那样。这可以通过下划线的bindAll-函数修复。我更新了我的回答,当然,当您将渲染绑定到事件时,您应该删除应用程序入口点代码中的渲染调用:
    this.$el.append(view.render().el)->
    此.el.append(view.el)在循环中附加DOM节点可能会对性能造成影响,我们可以渲染每个视图,然后一起推入DOM。如果我们已经像这里提到的那样引导了模型,该如何处理?嗨,这也是一个有趣的方法。稍后我们将仔细查看
    
    initialize: function() { // ContactView
      _.bindAll(this, 'render', 'otherMethodName', ...);
      ...
      this.render(); // Render in the end of initialize
    }
    
    // App.js
    var App = {}
    
    // ContactsCollection.js
    $(function(){
      var App.ContactsCollection = Backbone.Collection.extend({ ... });
    });
    
    // ContactsView.js
    $(function(){
      var App.ContactsView = Backbone.View.extend({ ... });
    });
    
    // and so on...
    
    // AppLoad.js
    $(function(){
    
      // instantiate the collection
      var App.contactsCollection = new App.ContactsCollection();
    
      // instantiate the CollectionView and assign the collection to it
      var App.contactsView = new App.ContactsView({
        el: "div.contacts-body ul",
        collection: App.contactsCollection
      });
    
      // fetch the collection the contactsView will
      // render the content authomatically
      App.contactsCollection.fetch();
    });
    
    var ContactsView = Backbone.View.extend({
      initialize: function( opts ){
        this.collection.on( 'reset', this.addAll, this );
        this.collection.on( 'add', this.addOne, this );
        // ... same with 'remove'
      },
    
      addOne: function( model ){
        var view = new App.ContactView({ model: contact });
        this.$el.append( view.render().el );
      },
    
      addAll: function(){
        this.collection.each( $.proxy( this.addOne, this ) );
      }
    });