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