我正在学习Marionette.js并有一个场景,我的应用程序有:
app.addRegions({
main: '#omen',
newItem: '#addnewitem',
counter: '#counter'
});
这些地区。我有这些模型/收藏:
var Item = Backbone.Model.extend(),
Items = Backbone.Collection.extend({
model: Item,
url: 'api/items'
}),
我有一个项目视图和项目视图:
ItemView = Mn.ItemView.extend({
tagName: 'tr',
template: '#itemView',
events: {
'click #btnDeleteBook' : 'deleteItem'
},
deleteItem: function() {
app.trigger('item:delete', this.model);
}
}),
ItemsView = Mn.CollectionView.extend({
tagName: 'table',
childView: ItemView,
onShow: function(view) {
TweenMax.staggerFrom($(view).find('td'), 1, {
x: 100
}, 2);
}
}),
我有一个初始化函数,它侦听上面的事件并通过app.ItemController完成。一切正常。
但是现在我想添加一个区域(计数器区域),它显示我的集合中的项目总数。理想情况下,我需要将它作为一个单独的视图,因为我将在不同的地方显示它。
所以我这样做:
DisplayCounter = Mn.ItemView.extend({
template: _.template('Total: '+ app.Items.length),
}),
app.Items
是上面声明的Collection
的实例。但即使在实例化DisplayCounter
之前,我也会收到错误:
未捕获的TypeError:无法读取属性'长度'未定义的。
请帮助...... :(
------------------------- EDIT --------------------- -
我已经实现了它,但做这么小的事情似乎太复杂了。
改变了我的收藏:
Items = Backbone.Collection.extend({
model: Item,
url: 'api/items',
initialize: function() {
this.listenTo(this, 'add', function() {
app.trigger('collection:updated', this);
});
}
}),
并改变了我的DisplayCounter:
DisplayCounter = Mn.ItemView.extend({
template: _.template('Total: <%=length%>'),
templateHelpers: function() {
return {
length: this.lengthVariable || 0
}
},
initialize: function() {
app.on('collection:updated', function(params){
this.lengthVariable = params.length;
this.render();
}.bind(this));
}
}),
我无法相信没有更简单的方法可以做到这一点..:/
答案 0 :(得分:1)
设置DisplayCounter
的代码在将Items
的实例放入app.Items
的代码之前运行。
即使您通过先指定app.Items
来避免此问题,您仍然会遇到问题 - template
属性只设置一次,因此您只能看到长度您定义app.Items
时的DisplayCounter
。
您应该在渲染时提供一个值,而不是将值直接硬编码到模板字符串中。 Mn.View.serializeData
允许您自定义在渲染时传递到模板函数的数据:
DisplayCounter = Mn.ItemView.extend({
template: _.template('Total:: <%= itemCount %>),
serializeData: function() {
return { itemCount: app.Items.length }
}
}),
答案 1 :(得分:0)
app.Items尚未定义。
在Marionette中,您可以定义要使用的视图集合或模型。
ItemsView = Mn.CollectionView.extend({
tagName: 'table',
childView: ItemView,
collection: myItems // An instance of your collection
onShow: function(view) {
TweenMax.staggerFrom($(view).find('td'), 1, {
x: 100
}, 2);
}
}),
所以marionette将在你的集合中为每个元素渲染一个itemView。然后在集合视图this.collection
内部将引用集合实例。因此this.collection.length
将满足您的需求。
在您的ItemView
中,您可以使用this.model