问题
I am working with an app that after every collection.fetch
, I need to drop in a random ad into the DOM. But, every time the collection fetches, and the ad is dropped in, it appears that the DOM is resetting itself instead of just appending new items to the overall collection container.
Here is the ItemView for the ad:
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;
});
CompositeView that holds the Products (I'm calling for a new ad after the collection is done sync
ing):
define(["marionette", "lodash", "text!fonts/products/template.html",
'fonts/products/item-view', 'fonts/products/model', 'eventer'],
function(Marionette, _, templateHTML, ProductItemView, ProductsModel, eventer) {
'use strict';
var ProductsView = Marionette.CompositeView.extend({
template: _.template(templateHTML),
childView: ProductItemView,
childViewContainer: '.items',
productsLimit: 150,
initialize: function() {
this.listenTo(eventer, 'sort:products', this.sortCollection, this);
this.listenTo(this.collection, 'sync', this.setupSync, this);
},
sortCollection: function(field) {
this.collection.sortByKey(field);
},
setupSync: function() {
this.setupWindowScrollListener();
this.adGeneration();
},
adGeneration: function() {
var child = this.children.last();
eventer.trigger('generate:new:ad', child);
},
productsEnd: function() {
eventer.trigger('products:end');
},
setupWindowScrollListener: function() {
var $window = $(window),
$document = $(document),
that = this,
collectionSize = that.collection.length;
if(collectionSize <= that.productsLimit) {
$window.on('scroll', _.throttle(function() {
var scrollTop = $window.scrollTop(),
wHeight = $window.height(),
dHeight = $document.height(),
margin = 200;
if(scrollTop + wHeight > dHeight - margin) {
eventer.trigger('fetch:more:products');
$window.off('scroll');
}
}, 500));
} else {
that.productsEnd();
}
},
});
return ProductsView;
});
回答1:
From your previous question I noticed that you're passing { reorderOnSort: false }
to your ProductsView
. This will cause your CompositeView
to re-render on a sort event. Since a 'sort'
event is triggered by Collection.set()
, you'll have to pass { reorderOnSort: true }
to ensure that your CompositeView
is not re-rendered after a fetch
→ set
→ sort
.
Note: If your CompositeView
defines a filter
method and the children are filter
'ed when new models are fetched, the CompositeView
will re-render.
来源:https://stackoverflow.com/questions/31383640/marionette-drop-in-new-itemview-after-every-fetch-not-working