【问题标题】:How can I pass a backbone.js collection to a view and iterate over the collection, then render the view?如何将backbone.js 集合传递给视图并遍历集合,然后渲染视图?
【发布时间】:2013-03-05 13:03:05
【问题描述】:

过去,我一直在做的是,当我想用​​模板渲染和显示集合时,只需调用集合上的“each”方法。对于每个模型,我为每个模型创建一个新的单一视图并将其附加到 $el.但在这种情况下,这是行不通的。我的模板中有一个输入类型文本,我不想为每个模型显示一个新输入。我宁愿以某种方式将集合传递给模板并迭代模板中的集合。另外值得注意的是,在创建此视图的新实例时,我的集合是通过我的主应用程序视图传入的:

// clientsview.js

define(
[
    'backbone',
    'ClientView',
    'Clients'
], function(Backbone, ClientView, Clients) {

ClientsView = Backbone.View.extend({

    tagName: '#page',
    template: _.template( $('#allClientsTemplate').html() ),


    initialize: function() {
        this.render();
    },

    render: function() {

        // var that = this;
        console.log('collection');
        console.log(this.collection);// successfully returns collection
        console.log('template');
        console.log(this.template);// successfully returns template function


        // This causes an error: 
        //Uncaught TypeError: Cannot call method 'toJSON' of undefined 
        var tmpl = this.template({ clients: this.collection.toJSON() });

        return this;

    }

});
return ClientsView;
});

我在 index.html 中的模板

// index.html
<script id="allClientsTemplate" type="text/template">
// I do not want create an input for every single model
// but I need the input to be part of the view.
<input type="text" class="table-search" id="search" autocomplete="off"   placeholder="Search Clients…">
<table class="table" id="tblData">
    <thead>
        <tr>
            <th>First Name</th>
            <th>Last Name</th>
            <th>Status</th>
        </tr>
    </thead>
    <tbody id="tblDataBody">

        <% _.each(clients, function(client) { %>

            <tr>
                <td><a href=""><%- client.first_name %></a></td>
                <td><a href=""><%- client.last_name %></a></td>
                <td><a href=""><%- client.status %></a></td>
            </tr>

        <% }); %>

    </tbody>
</script>

我正在从我的主应用视图中实例化我的客户视图:

define(
    [
        'jquery',
        'underscore',
        'backbone',
        'AddClientView',
        'ClientsView',

    ], function( $, _, Backbone, AddClientView, ClientsView ) {

    AppView = Backbone.View.extend({

        initialize: function() {

            // var addClientView = new AddClientView({ collection: this.collection });
            var clientsView   = new ClientsView({ collection:this.collection });


        }

    });
    return AppView;
});

我正在从我的初始化方法实例化我的主应用程序视图:

define('App', [
    'jquery',
    'underscore',
    'backbone',
    'Router',
    'bootstrap',
    'Clients',
    'AppView'
], function($, _, Backbone, Router, bootstrap, Clients, AppView) {

    function initialize() {

        // for custom global events
        window.vent = _.extend( {}, Backbone.Events )

        var app = new Router();
        Backbone.history.start();


        // probably more appropriate to do this in app view
        var clients = new Clients;// Get collection of clients


        clients.fetch().then( function() {// fetch client collection from db
            new AppView({ collection: clients });
        });

    }
    return {
        initialize: initialize
    };
});

我的初始化方法是从 main.js 调用的:

// main.js
require.config({
    shim: {
        'underscore': {
         exports: '_'
        },
        'backbone': {
            deps: ['underscore', 'jquery'],
            exports: 'Backbone'
        },
        'bootstrap': {
            deps: ['jquery'],
            exports: 'bootstrap'
        }
    },
    paths: {
        'text'          : 'lib/require/text',
        'jquery'        : 'lib/jquery/jquery-1.9.1',
        'underscore'    : 'lib/underscore/underscore',
        'backbone'      : 'lib/backbone/backbone',
        'bootstrap'     : 'lib/bootstrap/bootstrap',
        'App'           : 'app',
        'Router'        : 'router',
        'AppView'       : 'views/app/appview',
        'Client'        : 'models/clients/client',
        'Clients'       : 'collections/clients/clients',
        'ClientView'    : 'views/clients/clientview',
        'ClientsView'   : 'views/clients/clientsview',
        'AddClientView' : 'views/clients/addclientview'
    }
});
require(['App'], function(App) {
    App.initialize();
});

我在尝试这种方法时遇到错误(未捕获的类型错误:无法调用未定义的方法“toJSON”)。我怎样才能做到这一点?

【问题讨论】:

  • 你是如何实例化ClientsView的?您是否将collection 选项传递给new ClientsView(...)
  • @StuartM Stuart,查看我的更新。我添加了更多代码来尝试帮助解释我在这里做什么。希望这会有所帮助。
  • 为什么ClientsViewAppView是全局变量?你的toJSON 错误来自哪里?顺便说一句,console.log 是可变参数,所以你可以说console.log(a, b, c)
  • @muistooshort 感谢您指出全局变量问题。当我在路径中添加这些文件时,我什至不知道 require 正在创建全局变量。我认为 require 只是创建对这些文件和视图的引用。无论如何,现在可以使用了.. 将很快发布代码
  • require 不是在制作全局变量,你是。 pancakes = 11 是全局的,var pancakes = 11 是局部的;如果没有var,那么你有一个全局变量。

标签: jquery backbone.js underscore.js


【解决方案1】:

你的主干是正确的。您的问题是,当您实例化 AppView 时,您没有通过 fetch 创建的承诺传递数据:

你的代码:

clients.fetch().then( function() {// fetch client collection from db
     new AppView({ collection: clients });
});

应该是:

clients.fetch().then( function(resp) {// fetch client collection from db
     new AppView({ collection: resp.data });
});

【讨论】:

    【解决方案2】:

    您必须实例化您的集合,向其中添加项目,然后实例化视图并将集合传递给它:

    var clients= new Clients();
    clients.add({FirstName: 'Joe', LastName: 'Blow', Status: 'Active' });
    
    var clientsView = new ClientsView({collection: clients});
    

    您还需要更改您的模板:

    <% _.each(collection, function(client) { %>
    <tr>
        <td><a href=""><%- client.get('FirstName') %></a></td>
        <td><a href=""><%- client.get('LastName') %></a></td>
        <td><a href=""><%- client.get('Status') %></a></td>
    </tr>
    <% }); %>
    

    【讨论】:

    • 如果您查看我帖子中的第四个代码块,我正在实例化我的集合并调用其上的 fetch 方法以从数据库中获取所有项目。他们我将集合传递给我的 appview,然后从那里我将它传递给我的 clientsview。
    • @Scotty,你能确认 1 - console.log(this.collection),集合不包含任何未定义的对象,2 - 你能用“that”代替“this”吗: var tmpl = this.template({ clients: that.collection.toJSON() });
    猜你喜欢
    • 1970-01-01
    • 2016-05-19
    • 1970-01-01
    • 1970-01-01
    • 2011-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多