当子视图从Backbone中的服务获取JSON数据时,在父项中呈现子视图

时间:2013-04-19 06:58:41

标签: javascript model-view-controller backbone.js view underscore.js

尝试在父视图中渲染子视图时解决此问题。

父视图是一个静态的html块,它将是用于过滤子视图的选项卡,子视图是从服务器中提取的表格数据。

问题是父视图和子视图渲染正常,但子视图的集合没有数据;但我可以确认该服务正在控制台中返回数据。

这是我的路由器:

define([
    'domLib',
    'underscore',
    'backbone',
    'bootstrap',
    'view/logged-out',
    'view/leaderboard',
    'view/leaderboard-filter',  
    'view/leaderboard-overall',
    'view/login',
    'view/navigation'
], function($, _, Backbone, Bootstrap, LoggedOutView, LeaderboardView, LeaderboardFilter, OverallLeaderboardView, LoginView, NavigationView) {
    var AppRouter = Backbone.Router.extend({
        routes: {
            '': 'index',
            'leaderboard': 'leaderboard',
            'login': 'login'
        },
        index: function () {
            var loggedOutView = new LoggedOutView();
        },
        leaderboard: function(){
            var leaderboardFilter = new LeaderboardFilter();
            //var overallLeaderboardView = new OverallLeaderboardView();
        },
        login: function(){
            var loginView = new LoginView();
        }
    });

    var initialize = function(){

        var app_router = new AppRouter,
            leaderboardView = new LeaderboardView(),
            navigationView = new NavigationView();

        Backbone.history.start();
    };

    return {
        initialize: initialize
    };
});

我的父视图,从路由器调用:

define([
    'domLib',
    'underscore',
    'backbone',
    'router',
    'view/leaderboard-overall',
    'text!template/leaderboard-filter.html'
    ],
    function($, _, Backbone, Router, OverallLeaderboardView, LeaderboardFilterTemplate) {

        var LeaderboardFilterView = Backbone.View.extend({
            el: 'section[role="main"]',
            template: _.template(LeaderboardFilterTemplate),
            initialize: function(){
                this.innerView = new OverallLeaderboardView();
                this.render();
            },
            render: function(){
                this.$el.append(this.template());
                this.$el.append(this.innerView.render());
            }
        });

        return LeaderboardFilterView;
});

然后我想在父视图模板HTML中呈现一个表视图:

define([
    'domLib',
    'underscore',
    'backbone',
    'router',
    'collection/leaderboard-overall',
    'text!template/leaderboard-overall.html'
    ],
    function($, _, Backbone, Router, OverallLeaderboardCollection, OverallLeaderboardTemplate) {

        var OverallLeaderboardView = Backbone.View.extend({
            el: 'section[role="main"]',
            template: _.template(OverallLeaderboardTemplate),
            initialize: function(){
                this.collection = new OverallLeaderboardCollection();
                this.collection.bind('reset', _.bind(this.render, this));
                this.collection.fetch();
            },
            render: function(){
                console.log('render overall leaderboard');
                this.$el.append(this.template({players: this.collection.toJSON()}));
            }
        });

        return OverallLeaderboardView;
});

父模板(想要在.tab窗格中呈现子视图):

<nav id="leaderboard-filter">
    <ul class="nav nav-tabs">
        <li class="active"><a href="#all-time">All Time</a></li>
        <li><a href="#today">Today</a></li>
        <li><a href="#week">This Week</a></li>
        <li><a href="#month">This Month</a></li>
    </ul>
</nav>
<section>
    <div class="tab-content">
        <div class="tab-pane">
            <!-- Render leaderboard -->
        </div>
    </div>  
</section>

子视图:

<table class="table table-bordered table-striped">
    <thead>                             
        <tr>
            <th>Rank</th>
            <th>Player</th>
            <th>Games Completed</th>
            <th>High Score</th>
            <th>Percent Correct</th>
            <th>Avg Answer Time</th>
            <th>Cumulative Score</th>
        </tr>
    </thead>
    <tfoot>
        <!-- Logged in user details here -->
    </tfoot>
    <tbody>
        <% _.each(players, function(player, index){ %>
            <tr>
                <td><%= index + 1 %></td>
                <td><a href="/hyc-web/"><%= _.escape(player.user) %></a></td>
                <td><%= player.games_completed %></td>
                <td><%= player.high_score %></td>
                <td><%= player.percent_correct %></td>
                <td><%= player.avg_answer_time %></td>
                <td><%= player.cumulative_score %></td>
            </tr>           
        <% }); %>                                   
    </tbody>
</table>

两者都按顺序渲染,但子视图不会仅仅为表头呈现任何数据。

可以;弄清楚如何使这个工作?

3 个答案:

答案 0 :(得分:1)

您应该在追加时指定孩子的el。

this.$el.append(this.innerView.render());

this.$el.append(this.innerView.render().el);

答案 1 :(得分:1)

请参阅RullDawg对部分问题的回答 另一部分是,在升级到Backbone 1.0时,您可能会错过一些事情。

重命名集合的”更新“以设置,与类似的model.set()并行,并与reset对比。它现在是获取后的默认更新机制。如果你想继续使用”重置“,传递{reset:true}。

所以基本上,你渲染你的子视图的唯一时间是你在父视图中渲染它(我不知道你为什么要这样做btw)。您在reset事件从未触发时收听。将其更改为this.collection.fetch({reset: true});,并注意您要添加到DOM的内容,它应该可以正常工作。

如果您不想使用reset标记,则可以收听更通用的sync事件。

答案 2 :(得分:1)

我的理解是,当集合在后端有数据时,它不会渲染数据。 现在你的代码存在缺陷。 fetch()是异步调用。 因此,为了确保您的数据可用,而渲染视图是写入成功处理程序。 并将你的fetch逻辑移动到render()函数 例如 如果我在OverAllLeatherBoardView中看到你的提取代码

initialize: function(){
            this.collection = new OverallLeaderboardCollection();
            this.collection.bind('reset', _.bind(this.render, this));
            //this.collection.fetch(); move it to render function
        },
        render: function(){
            console.log('render overall leaderboard');
            this.collection.fetch({success: $.proxy(myDelegate, this)})
            //this.$el.append(this.template({players: this.collection.toJSON()})); move it to delegate
        },
        //here you go
        mDelegate:function(model, response, options){
          this.$el.append(this.template({players: model.toJSON()}));
        }