Backbone.js 主干网/木偶网获取大集合会导致浏览器冻结

Backbone.js 主干网/木偶网获取大集合会导致浏览器冻结,backbone.js,marionette,Backbone.js,Marionette,我在木偶网中使用了一个CompositeView,当集合获取时,它可能会从API中提取1000条记录。我看到的问题是,当用户界面加载时,浏览器会摆动,脚本会冻结浏览器 我试着关注这篇博文,但似乎不知道如何将其转化为木偶作品 这是我的合成视图: 我的项目视图如下所示: var EmailItemView = Marionette.ItemView.extend({ tagName: 'article', template: _.template(templateH

我在木偶网中使用了一个CompositeView,当集合获取时,它可能会从API中提取1000条记录。我看到的问题是,当用户界面加载时,浏览器会摆动,脚本会冻结浏览器

我试着关注这篇博文,但似乎不知道如何将其转化为木偶作品

这是我的合成视图:

我的项目视图如下所示:

var EmailItemView = Marionette.ItemView.extend({
        tagName: 'article',

        template: _.template(templateHTML),

        ui: {
            radio: 'label input',
            img: 'figure img',
            figure: 'figure'
        },

        events: {
            'click': 'onSelect',
            'click @ui.radio': 'onSelect'
        },

        modelEvents: {
            'change': 'render'
        },

        behaviors: {
            Filter: {
                behaviorClass: Filter,
                field: "email_name"
            }
        },

         /**
         * initializes this instance with passed options from the constructor
         * @method EmailItemView.initialize
         */
        initialize: function(options){
            this.parentIndex = options.parentIndex;
            this.parentContainer = options.parentContainer;

            this.listenTo(eventer, 'menu:scroll', this.onScroll, this);
        },

        /**
         * Runs automatically when a render happens. Sets classes on root element.
         * @method EmailItemView.onRender
         */
        onRender: function () {
            var checked = this.model.get("checked");
            this.$el.toggleClass('selected', checked);
            this.ui.radio.prop('checked', checked);
        },

        /**
         * Runs after the first render, only when a dom refrsh is required
         * @method EmailItemView.onDomRefresh
         */
        onDomRefresh: function(){
            this.onScroll();
        },

        /**
         * Marks this item as checked or unchecked
         * @method EmailItemView.onSelect
         */
        onSelect: function () {
            this.model.collection.checkSingle(this.model.get('id'));
            this.trigger('menu:selected:email');
        },

        templateHelpers: {
            formattedDate: function() {
                var date = this.updated_ts.replace('@D:', '');
                if (date !== "[N/A]") {
                    return new Moment(date).format('dddd, MMMM DD, YYYY [at] hh:mm a');
                }
            }
        },

        /**
         * Delays the load of this view's thumbnail image until it is close to
         * being scrolled into view.
         * @method EmailItemView.onScroll
         */
        onScroll: function () {
            if (this.parentIndex < 10) {
                // if it's one of the first items, just load its thumbnail
                this.ui.img.attr('src', this.model.get('thumbnail') + '?w=110&h=110');
            } else if (this.parentContainer.length && !this.ui.img.attr('src')) {
                var rect = this.el.getBoundingClientRect(),
                    containerRect = this.parentContainer[0].getBoundingClientRect();
                // determine if element is (or is about to be) visible, then
                // load thumbnail image
                if (rect.top - 300 <= containerRect.bottom) {
                    this.ui.img.attr('src', this.model.get('thumbnail') + '?w=110&h=110');
                }
            }
        }
    });

我试图调整我的CompositeView,使其能够构建HTML,然后呈现缓存的HTML,而不是附加1000个元素

呈现所有1000个元素不是个好主意-DOM将变得太大。另外,在fetch上,所有1000个模型都有解析,并且它是同步工作的。所以有两种方法-加载更少的数据,或者按块解析/呈现splist数据

为什么要在onRender方法中获取集合?您可以在成功回调之前和回调中获取它,初始化CompositeView并将集合作为选项传递。在这种情况下,CompositeView将为您处理所有附加/缓存/碎片化的事情。
var EmailItemView = Marionette.ItemView.extend({
        tagName: 'article',

        template: _.template(templateHTML),

        ui: {
            radio: 'label input',
            img: 'figure img',
            figure: 'figure'
        },

        events: {
            'click': 'onSelect',
            'click @ui.radio': 'onSelect'
        },

        modelEvents: {
            'change': 'render'
        },

        behaviors: {
            Filter: {
                behaviorClass: Filter,
                field: "email_name"
            }
        },

         /**
         * initializes this instance with passed options from the constructor
         * @method EmailItemView.initialize
         */
        initialize: function(options){
            this.parentIndex = options.parentIndex;
            this.parentContainer = options.parentContainer;

            this.listenTo(eventer, 'menu:scroll', this.onScroll, this);
        },

        /**
         * Runs automatically when a render happens. Sets classes on root element.
         * @method EmailItemView.onRender
         */
        onRender: function () {
            var checked = this.model.get("checked");
            this.$el.toggleClass('selected', checked);
            this.ui.radio.prop('checked', checked);
        },

        /**
         * Runs after the first render, only when a dom refrsh is required
         * @method EmailItemView.onDomRefresh
         */
        onDomRefresh: function(){
            this.onScroll();
        },

        /**
         * Marks this item as checked or unchecked
         * @method EmailItemView.onSelect
         */
        onSelect: function () {
            this.model.collection.checkSingle(this.model.get('id'));
            this.trigger('menu:selected:email');
        },

        templateHelpers: {
            formattedDate: function() {
                var date = this.updated_ts.replace('@D:', '');
                if (date !== "[N/A]") {
                    return new Moment(date).format('dddd, MMMM DD, YYYY [at] hh:mm a');
                }
            }
        },

        /**
         * Delays the load of this view's thumbnail image until it is close to
         * being scrolled into view.
         * @method EmailItemView.onScroll
         */
        onScroll: function () {
            if (this.parentIndex < 10) {
                // if it's one of the first items, just load its thumbnail
                this.ui.img.attr('src', this.model.get('thumbnail') + '?w=110&h=110');
            } else if (this.parentContainer.length && !this.ui.img.attr('src')) {
                var rect = this.el.getBoundingClientRect(),
                    containerRect = this.parentContainer[0].getBoundingClientRect();
                // determine if element is (or is about to be) visible, then
                // load thumbnail image
                if (rect.top - 300 <= containerRect.bottom) {
                    this.ui.img.attr('src', this.model.get('thumbnail') + '?w=110&h=110');
                }
            }
        }
    });