我在CompositeView
中有一个Marionette
,当集合提取时可能会从API中提取1000条记录。我看到的问题是,当UI加载时,浏览器会退出并且脚本会冻结浏览器。
我已尝试关注此博文(http://lostechies.com/derickbailey/2011/10/11/backbone-js-getting-the-model-for-a-clicked-element/),但似乎无法弄清楚如何将其转换为Marionette
。
这是我的CompositeView
:
var EmailsMenuView = Marionette.CompositeView.extend({
template: _.template(templateHTML),
childView: EmailItemView,
childViewOptions: function(model, index){
return {
parentIndex: index,
parentContainer: this.$el.closest('form')
};
},
childViewContainer: '.emails',
ui: {
emails: '.emails',
options: '.email-options',
subject: "#subject_line",
fromName: "#from_name",
fromEmail: "#from_email",
thumbnail: '.thumbnail img',
emailName: '.thumbnail figcaption'
},
events: {
'change @ui.subject': 'onSubjectChange',
'change @ui.fromName': 'onFromNameChange',
'change @ui.fromEmail': 'onFromEmailChange'
},
childEvents: {
'menu:selected:email': 'onMenuEmailSelect'
},
collectionEvents: {
'change:checked': 'onEmailSelected'
},
behaviors: {
EventerListener: {
behaviorClass: EventerListener,
eventerEvents: {
'menu:next-click': 'onNext',
'menu:previous-click': 'onPrev'
}
},
LoadingIndicator: {
behaviorClass: LoadingIndicator,
parentClass: '.emails'
}
},
renderItem: function(model) {
console.log(model);
},
/**
* Runs automatically during a render
* @method EmailsMenuView.onRender
*/
onRender: function () {
var colCount, showGridList, selected,
threshold = 300;
if(this.model.get('id')) {
selected = this.model;
}
// refresh its list of emails from the server
this.collection.fetch({
selected: selected,
success: function (collection) {
colCount = collection.length;
console.log(colCount);
},
getThumbnail: colCount <= threshold
});
this.collection.each(this.renderItem);
var hasEmail = !!this.model.get('id');
this.ui.emails.toggle(!hasEmail);
this.ui.options.toggle(hasEmail);
eventer.trigger(hasEmail ? 'menu:last' : 'menu:first');
}
});
我的ItemView看起来像这样:
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个元素
答案 0 :(得分:0)
渲染所有1000个元素并不是个好主意 - DOM会变得太大。此外,在获取时,所有1000个模型都有解析,并且它可以同步工作。所以有两种方法 - 加载较少的数据,或splist数据来解析/渲染块