收集同步后,木偶CompositeView children.findByIndex无法按预期工作 [英] Marionette CompositeView children.findByIndex not working as expected after collection sync
问题描述
在收集同步之后的 中,我有以下代码:
I have the following code that happens after a collection sync:
adGeneration: function() {
var child = this.children.findByIndex(this.children.length - 1);
console.log(child.model.toJSON());
eventer.trigger('generate:new:ad', child);
},
我遇到的问题是,在第一次同步后,child
元素是一个空白模型:
The problem I am running into, is that, after the first sync, the child
element is a blank model:
第一次:
Object {id: "5-vp39kv3uiigxecdi", size: 26, price: "9.84", face: "( ⚆ _ ⚆ )"}
每次之后:
Object {length: 40, models: Array[41], _byId: Object, _listeningTo: Object, _listenId: "l14"…}
ProductsCollection
ProductsCollection
define(["backbone", "lodash", "fonts/products/model", "eventer"],
function(Backbone, _, ProductModel, eventer) {
'use strict';
var ProductsCollection = Backbone.Collection.extend({
model: ProductModel,
sort_key: 'price',
url: '/api/products',
offset: 0,
initialize: function() {
this.listenTo(eventer, 'fetch:more:products', this.loadMore, this);
},
comparator: function(item) {
return item.get(this.sort_key);
},
sortByKey: function(field) {
this.sort_key = field;
this.sort();
},
parse: function(data) {
return _.chain(data)
.filter(function(item) {
if(item.id) {
return item;
}
})
.map(function(item){
item.price = this.formatCurrency(item.price);
return item;
}.bind(this))
.value();
},
formatCurrency: function(total) {
return (total/100).toFixed(2);
},
loadMore: function() {
this.offset += 1;
this.fetch({
data: {
limit: 20,
skip: this.offset
},
remove: false,
success: function(collection) {
this.add(collection);
}.bind(this)
});
}
});
return ProductsCollection;
});
LayoutView包含productions集合的View.该集合是在layoutview的onShow上获取的
LayoutView that contains the View for the productions collection. The collection is fetched onShow of the layoutview
define(["marionette", "lodash", "text!fonts/template.html",
"fonts/controls/view", "fonts/products/view", "fonts/products/collection", "eventer"],
function(Marionette, _, templateHTML, ControlsView, ProductsView,
ProductsCollection, eventer) {
'use strict';
var FontsView = Marionette.LayoutView.extend({
regions: {
controls: '#controls',
products: '#products-list'
},
template: _.template(templateHTML),
initialize: function() {
this._controlsView = new ControlsView();
this._productsView = new ProductsView({
collection: new ProductsCollection({
reorderOnSort: false,
sort: false
})
});
this.listenTo(this._productsView.collection, 'sync', this.loading, this);
this.listenTo(eventer, 'fetch:more:products', this.loading, this);
this.listenTo(eventer, 'products:end', this.productsEnd, this);
},
onRender: function() {
this.getRegion('controls').show(this._controlsView);
this.getRegion('products').show(this._productsView);
this.loading();
},
onShow: function() {
this._productsView.collection.fetch({
data: {
limit: 20
}
})
},
productsEnd: function() {
this.loading();
this.$el.find('#loading').html("~ end of catalogue ~")
},
loading: function() {
var toggle = this.$el.find('#loading').is(':hidden');
this.$el.find('#loading').toggle(toggle);
}
});
return FontsView;
});
AdsView:
define(["marionette", "lodash", "text!ads/template.html", "eventer"],
function(Marionette, _, templateHTML, eventer) {
'use strict';
var AdsView = Marionette.ItemView.extend({
template: _.template(templateHTML),
ui: {
ad: '.ad'
},
initialize: function() {
this.listenTo(eventer, 'generate:new:ad', this.generateNewAd, this);
},
onShow: function() {
// Set add image onShow
this.ui.ad.prop('src', '/ad/' + this.randomNumber());
},
generateNewAd: function(childView) {
var newAd = this.ui.ad.clone(),
element = childView.$el,
elementId = childView.model.get("id");
newAd.prop('src', '/ad/' + this.randomNumber());
$("#" + elementId).after(newAd);
},
randomNumber: function() {
return Math.floor(Math.random()*1000);
},
setUpAd: function() {
this.ui.ad.prop('src', '/ad/' + this.randomNumber());
}
});
return AdsView;
});
推荐答案
我认为您的问题出在ProductsCollection.loadMore
方法中.在那里,在您的fetch
的success
回调中,
I think your problem is in the ProductsCollection.loadMore
method. There, in the success
callback to your fetch
you do,
function(collection) { this.add(collection); }
幕后发生的事情是,在调用success
回调之前,Backbone首先将对数据运行Collection.set()
.默认情况下,在set
内部,您的数据将被解析为ProductsCollection.parse
返回的模型数组,并且如果找到任何新模型,它们将被add
编辑到您的现有集合中(请注意,除非您通过{ remove: false }
到您的fetch
选项,集合中在上一次提取中不是不是的模型将被删除.请参见 Collection.set
)
What's happening behind the scenes is that before your success
callback is invoked, Backbone will first run Collection.set()
on your data. By default, inside set
your data will be parsed into a array of models returned by ProductsCollection.parse
and if any new models are found they will be add
'ed to your existing collection (note that unless you pass { remove: false }
to your fetch
options, models in your collection which are not in your last fetch will be removed. See Collection.set
)
因此,当您在loadMore
中执行fetch
(在第一个fetch
之后之后称为)时会发生什么,Backbone首先会从服务器中add
所有模型(即从ProductsCollection.parse
返回),然后调用fetch
的success
回调,这实际上是最后一个add
. add
'ing是ProductsCollection
实例.不是collection.models
而是模型数组,而是具有属性models
的Backbone对象,该属性保存原始模型数组.因此,奇怪的输出:
So, what happens when you do the fetch
in loadMore
, which is called after the first fetch
, Backbone will first add
all the models from the server (that are returned from ProductsCollection.parse
) and then invoke the success
callback of your fetch
, which, essentially does one last add
. And what it's add
'ing is the ProductsCollection
instance. Not collection.models
, an array of models, rather a Backbone object that has a property models
that holds a raw array of models. Hence, the strange output:
Object {length: 40, models: Array[41], _byId: Object, _listeningTo: Object,
_listenId: "l14"…}
只需删除该success
回调(这是不必要的),并且ProductsView
的最后一个子视图应该是从返回的最后一个模型呈现的视图.
Simply remove that success
callback (which is unnecessary) and the last child view of your ProductsView
should be the view rendered from the last model returned.
这篇关于收集同步后,木偶CompositeView children.findByIndex无法按预期工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!