Marionette CompositeView在setElement上取消分配childview事件

时间:2015-09-21 23:20:10

标签: javascript marionette backbone-views backbone-events

我有一个marionette compositeview我正用于为应用中的个人资料页面创建项目列表。对于子视图,我从已存​​在的ItemView扩展。

当我在this.setElement(this.el.innerHTML) compositeview函数中使用onRender时,子视图中设置的所有事件不再被触发,甚至更多,在检查器的控制台中触发它们浏览器中的工具,什么都不做。

但是,当我不使用setElement时,容器div会添加到我的标记中,但现在子视图中的所有事件都有效。

有人可以帮我理解这一点。

我正在使用的Collection有一个自定义clone方法。

我正在使用一个全局集合,它在每次获取时都会更新并存储在缓存中。

当我实际实例化我的视图时,该集合已被使用,并且主layout视图中的某个区域已填充了类似于我想要渲染的项目列表。

这是我实例化视图的方式:

var currentUser = Profile.get('username');

        // Perform changes to global collection
        Items.url = API + '/items/search?q=' + currentUser + '&size=20';

        Items.parse = function (response) {

            if (!response.results) {
                return response;
            } else {
                return response.results;
            }
        };

        Items.fetch(
            {success: function (collection, response, options) {

                this.listOfItems = new View.itemListProfilePage({
                    template: TemplIds.profilePagePostedItems,
                    parentClass: 'profile-cols',
                    collection:  Items, // global collection
                    filterAttr: {user: currentUser},
                    isFiltered: true,
                    lazyLoad: true,
                    childViewContainer: '#profile-items',
                    childView: View.itemProfilePage.extend({
                        template: TemplIds.item
                    })
                });

                Backbone.trigger('main:show', this.listOfItems); //'main:show' is an event in layoutview which calls region.show

            },
                remove: false
        });

我的compositeview

View.itemListProfilePage = Marionette.CompositeView.extend({
    collection: null,       //original collection cloned later for filtering
    fetch: null,            //promise for fetched items
    lazyView: null,

    options: {
        parentClass: '',
        filterAttr: {},
        isFiltered: false,
        lazyLoad: false
    },

    initialize: function () {

        this.stopListening(this.collection);

        //Change collection property and re-apply events
        this.collection = this.collection.clone(this.options.filterAttr, this.options.isFiltered);
        this._initialEvents();

        this.collection.reset(this.collection.where(this.options.filterAttr), {reset: true});

        this.listenTo(Backbone, 'edit:profileItems', this.addEditClassToSection);

    },

    onRender: function () {

        this.setElement(this.el.innerHTML, true);

    },

    onShow: function () {

        if (this.options.parentClass) {
            this.el.parentElement.className = this.options.parentClass;
        }
    },

    addEditClassToSection: function (options) {

        if ( options.innerHTML !== 'edit' ) {
            this.el.classList.add('edit-mode');
        } else {
            this.el.classList.remove('edit-mode');
        }
    },
}

ItemView

View.Item = Marionette.ItemView.extend({
    model: null,
    numLikes: null,             //live set of DOM elements containing like counter
    modalItem: null,            //view class with further details about the item to be used within a modal       

    events: {
        'click img.highlight': 'showModal'
    },

    initialize: function (options) {
        var itemWithHeader;     //extended item view class with header at the top and no footer
        var addToCart;

        //Set up all like-related events
        this.listenTo(this.model, "change:numLikes", this.updateNumLikes);
        this.listenTo(this.model, "change:liked", this.updateLiked);

        //Set up the view classes to be used within the modal on click
        itemWithHeader = View.ItemWithHeader.extend({
            template: this.template,
            model: this.model               //TODO: move to inside itemDetails
        });
        itemAddToCart = View.ItemAddToCart.extend({
            template: TemplIds.itemAddCart,
            model: this.model               //TODO: move to inside itemDetails
        });
        this.modalItem = View.ItemDetails.extend({
            template: TemplIds.itemDetails,
            model: this.model,
            withHeader: itemWithHeader,
            addToCart: itemAddToCart
        });
    },

    onRender: function () {
        var imgContainerEl; 
        var likeButtonEl;

        //Get rid of the opinionated div
        this.setElement(this.el.innerHTML);
        this.numLikes = this.el.getElementsByClassName('num');

        //Add the like button to the image
        likeButtonEl = new View.LikeButton({
            template: TemplIds.likeButton,
            model: this.model
        }).render().el;
        this.el.firstElementChild.appendChild(likeButtonEl);    //insert button inside img element
    },

    showModal: function (evt) {

        var modalView = new View.Modal({
            views: {
                'first': {view: this.modalItem}
            }
        });

        Backbone.trigger('modal:show', modalView);
    },
});

列表中每个项目的itemView:

View.itemProfilePage =  View.Item.extend({

    events: _.extend({},View.Item.prototype.events, {
            'click .delete-me': 'destroyView'
        }
    ),

    onRender: function () {

        View.Item.prototype.onRender.call(this);

        this.deleteButtonEl = new View.itemDeleteButton({
            template: TemplIds.deleteButton
        }).render().el;

        this.el.firstElementChild.appendChild(this.deleteButtonEl);

    },

    destroyView: function (evt) {

        this.model.destroy();

    }

});

0 个答案:

没有答案