Backbone子视图未正确呈现

时间:2015-01-21 13:37:54

标签: javascript backbone.js

我开始使用backbone.js开发一个网站,在整个上午尝试之后,我完全坚持以下问题。

我这里仅输出相关代码。

我是一个名为Navigator的视图,其中包含一个记录集合(最初为空):

var NavigatorView = Backbone.View.extend({
    template: JST['app/scripts/templates/Navigator.ejs'],

    tagName: 'div',

    id: '',

    className: 'saiNavigator',

    events: {},

    initialize: function () {
        this.currentRecords = new RecordsCollection();
        this.currentRecords.on('reset', this.onRecordsCollectionReseted.bind(this));
    },
    onRecordsCollectionReseted: function(){
        this.render();
    },
    render: function () {
        var tplResult = this.template({
            computeTemplate: this.computeTemplate,
            records: this.currentRecords
        });
        this.$el.html(tplResult);
    },
    onDOMUpdated: function(){
        var me = this;
        var data = {
            device : 'web',
            gridId : this.model.get('gridId'),
            filterId : this.model.get('filterId')
        };

        $.ajax({
            url: App.getTokenedUrl() + '/task/getGridData.'+this.model.get('taskId')+'.action',
            success: me.onRecordReceived.bind(me),
            statusCode: {
                500: App.handleInternalError
            },
            type: 'GET',
            crossDomain: true,
            data : data,
            dataType: 'json'
        });
    },
    onRecordReceived: function(result){
        var newRecords = [];
        for(var i = 0; i < result.items.length; i++){
            var newRecord = new RecordModel(result.items[i]);
            newRecords.push(newRecord);
        }            
        this.currentRecords.reset(newRecords);
    }
});

我有一个名为档案的视图,html是

<div id="dossier1" class="dossier">
  <div id="dossier1-navContainer" class="navigatorContainer"/>   
  <div class="pagesNavigatorContainer"/>
  <div class="pagesContainer"/>
  <div class="readOnlyFiche"/>
</div>

当我第一次渲染档案(我只渲染一次)时,我在以下渲染功能中创建导航器

render: function () {
    this.$el.html(this.template({
        uniqBaseId: this.id,
        className: this.className
    }));

    var nav = this.navigator = new NavigatorView({
        model : this.model,
        id: this.id+'navigator',
        el: $('#'+this.id+'-navContainer')
    });

    this.navigator.render();
    //We notify the navigator that it's ready. This will allow the nav to load records
        nav.onDOMUpdated();
    }
}

正如我们所看到的,我给了#dossier1-navContainer&#39; id到导航器,以便他在那里渲染

所以,这是它的工作原理。当我渲染档案时,它会创建一个导航器并将其插入DOM中。完成后,我通知导航器它可以通过ajax请求从服务器加载其数据。当我收到答案时,我会使用传入记录重置数据集合。

在此之前的Juste。导航器渲染函数中的$ el.html(tplResult)输出结果字符串。

第一次

<div class="items"></div> 

第二次获得记录时,它是

<div class="items">
    <div>item1</div>
    <div>item2</div>
    <div>item3</div>
</div> 

因此模板生成是正确的。但是,当第二次渲染发生时,这个。$ el.html(tplResult)会执行 NOTHING 。如果我在浏览器中查看DOM NOTHING CHANGED

但是,如果我用

替换这一行
$('#dossier1-navigator').html(tplResult) 

它有效。这意味着第一次,$(&#39;#dossier1-navigator&#39;)和这个。$ el是同一个对象,第二次没有。

我不知道为什么第二次使用这个标准时没有工作。$ el。

帮助!!

提前致谢

编辑:在与Seebiscuit讨论了很多之后,我添加了几行有助于回答问题的内容

newTask.render();
var taskHtml = newTask.$el.html();
$('#mainTaskContainer').append(taskHtml);

3 个答案:

答案 0 :(得分:1)

我的预感是你有绑定问题。我建议你替换

 this.currentRecords.on('reset', this.onRecordsCollectionReseted.bind(this)); },

在您的initialize中:

this.listenTo(this.currentRecords, "reset", this.render);

无需特别绑定。 Backbone的listenTo对Backbone对象的回调出价,该对象设置了监听器(this中的this.listenTo)。还有一个额外的好处是当你关闭视图时(通过调用this.remove())它会删除监听器,并帮助你避免僵尸视图。

尝试一下。

答案 1 :(得分:0)

我认为问题在于您没有使用传递给navigatorView的内容;

在你的navigatorView中试试这个:

initialize:function(el) {
    this.$el=el
    ...
}

如果有帮助请告诉我

答案 2 :(得分:0)

经过与seebiscuit讨论无数分钟后,我们想出了解决方案。问题在于$ el元素的定义。形式定义将其定义为

  

视图元素的缓存jQuery对象。一个方便的引用,而不是一直重新包装DOM元素

从标准缓存的角度来看,这实际上并不十分精确。从我的观点来看,至少缓存的原理是在没有它的情况下查找值,否则使用它。但是在这种情况下并非如此。正如Seebiscuit告诉我的那样,

  

因为当你第一次绑定这个。$ el = $(someelement)这个。$ el将始终引用$(someelement)的返回而不是$(someelement)。差异何时重要?   当您执行赋值时元素不在DOM中

实际上,$ el持有第一次查找选择器的结果。因此,如果第一次查找未命中,那么它将永远不会成功!即使稍后添加元素。

我的错误是将主要的档案视图添加到DOM 之后呈现其NavigatorView子视图。如果$ el是一个真正的缓存我可以找到解决方案,因为ajax回调中的第二个渲染会找到该元素。按照目前的方式,我只做了一件事。

结论:在尝试渲染子视图时,确保视图的每个部分都在DOM中正确呈现。