Marionette drop in new ItemView after every fetch

2019-09-17 21:35发布

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 syncing):

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;
});

标签: marionette
1条回答
Luminary・发光体
2楼-- · 2019-09-17 21:53

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 fetchsetsort.

Note: If your CompositeView defines a filter method and the children are filter'ed when new models are fetched, the CompositeView will re-render.

查看更多
登录 后发表回答