我开始使用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);
答案 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中正确呈现。