我的结构非常简单
ProductsList.TileListView = Marionette.CollectionView.extend({
tagName: 'section',
className: 'b-list-viewtile',
template: '/static/js/app/list/modules/productslist/templates/tileList',
childView: ProductsList.TileItemView
});
ProductsList.TileItemView = Marionette.ItemView.extend({
tagName: "article",
className: "b-list-viewtile__item",
template: '/static/js/app/list/modules/productslist/templates/tileItem',
_getImage: function(){
var _this = this;
var img = new Image();
img.src = this.model.get("media");
img.onload = function(){
msnry.append( _this.$el )
.masonry( 'appended', _this.$el ).masonry('layout');
};
}
});
但我使用 Masonry 插件来对齐网格上的项目。
问题是,对于每个项目,我需要知道变量的值,例如图像的高度。
这意味着构建每个 itemView 我只能将前一个项目附加到 DOM 中。
维护集合中的顺序也很重要 - 集合中的第一个应该首先渲染,等等。
花了很多时间研究文档但没有找到优雅的解决方案
有人能告诉我如何构建那个“链”吗?每个项目都必须等待先前渲染,但最终结果顺序必须保持在集合中,而不是图像加载优先级中。
我认为这是关于 defered+marrionette.callback 并覆盖 native AttachHtml 或 buildChildView
非常感谢:)
最佳答案
我们将使用 Marionette 内置的 Marionette.Babysitter 和 ES6 Promises 来解决您的问题。
如果您阅读 docs仔细(或浏览源代码)您将了解到 Marionette 按集合顺序呈现 subview 。
By default the
CollectionView
will maintain the order of itscollection
in the DOM.
此外,所有 CollectionView 还将按照其渲染顺序保存对其所有 subview 的引用,这也是按照其集合排序顺序。
您想要的是确保所有 subview 都已渲染,然后添加该 subview el
到您的砌体项目列表,按顺序。
首先,设置您的 Promise
我们将修改您的 subview 的 ._getImage
稍微修改一下方法,并让它返回一个 Promise:
_getImage: function(){
var _this = this;
return new Promise(function (resolve, reject) {
var img = new Image();
img.src = this.model.get("media");
img.onload = function(){
resolve();
};
});
}
当加载此任意 subview 的图像时, getImage 返回的 promise 将得到解决。这对我们有什么帮助?继续阅读。
其次,等待所有图像加载完毕
在您的 CollectionView 中,您将添加此属性 onRenderCollection
,当所有 subview 完成渲染时,Marionette 会触发该事件。在这里,使用 Babysitter,我们将解雇 _getImage
方法,并设置您正在寻找的 Masonry promise 链。
onRenderCollection: function () {
var promises = [];
this.children.each(function (childview) {
promises.push(childview._getImage()); // return the promise
})
// When all your children view's images have loaded we begin to fill Masonry
Promise.all(promises).then(_.bind(function () {
this.children.each(function (childview) {
childview.addToMasonry();
}
}, this))
}
第三,添加到 Masonry!
当然,我们还没有名为 addToMasonry
的属性你 child 的观点,但我假设你会使用一个看起来很像你的img.onload
上的东西打回来。像这样的事情
addToMasonry: function () {
masonry.append( this.$el )
.masonry( 'appended', this.$el ).masonry('layout');
}
缺点
使用此方法的一个警告是,您首先必须等到所有 subview 都渲染完毕。如果列表很长(超过 1000 个),这可能是一个性能问题,并且解决方法可能并不简单。
关于javascript - 如何在 marrionete.js 中构建调用链渲染 itemView,并使用 itemView 内的异步函数进行延迟,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30330178/