前面文章《vuejs实现瀑布流布局(一)》和《vuejs实现瀑布流布局(二)》已经介绍了瀑布流的基本实现的一种方法,虽然是在vuejs中实现的,可是实际上也可以把这段代码扒出来,在我们的任何项目中使用,并不局限于vuejs。
我也在项目中用这段代码实现了这种瀑布流。
后来发现一个问题,就是瀑布流布局会在每次刷新之后,排序发生变化,如果讲究一点的话,其实并没有什么特别大的影响,可是如果追求精益求精的话,确实不太理想。
看一下,瀑布流实现的关键性代码:
$("#items").children("li").each(function (index, val) {
var $this = $(this);
var $img = $this.find("img").first();
$img.on("error", function () {
$img.attr("src", "../src/assets/images/default.png");
});
if ($img.get(0).complete) {
addItems();
} else {
$img.on("load", function () {
addItems();
});
}
function addItems() {
if(_this.leftHeight <= _this.rightHeight){
$l.append($this);
_this.leftHeight = $l.height();
}else{
$r.append($this);
_this.rightHeight = $r.height();
}
}
$.refreshScroller();
});
其中的addItems就是布局瀑布流的,但是当前存在的问题就是:当从后台取回数据之后,在id="items"的ul中渲染每一项列表时,一旦图片加载完成,就立马将其布局到页面中,这就必然导致每次刷新之后页面布局排序的顺序有所不同,因为我们没有办法预计哪条数据中的图片加载先完成。
如此,如果需要修复这个问题的话,似乎只有一个可提供的方案,等待所有图片在<ul id="items"></ul>中加载完成,然后在按顺序布局到页面中。
定义一个全局变量:
imgs: {
imgLoad: [],
loadNums: 0
}
在数据请求回来之后,把新请求回来的数据赋值给imgs.imgLoad,以保证imgs.imgLoad里面所存储的数据都是刚刚请求回来的数据,然后在<ul id="items"></ul>渲染之前,将imgs.loadNums = 0;重新赋值为0,然后<ul id="items"></ul>的列表li每次渲染加载img成功之后imgs.loadNums++,当imgs.loadNums值等于imgs.imgLoad的数组长度的时候,再开始页面布局。
$("#items").children("li").each(function (index, item) {
var $this = $(item);
var _img = $(item).find("img").first();
_img.on("error", function () {
_img.attr("src", "../src/assets/images/default.png");
});
_this.leftHeight = $l.height();
_this.rightHeight = $r.height();
if(_img.get(0).complete){
_this.imgs.loadNums++
} else {
_img.on("load", function () {
_this.imgs.loadNums++
waterfallLayer();
})
}
})
waterfallLayer()
function waterfallLayer() {
if (_this.imgs.loadNums == _this.imgs.imgLoad.length) {
$("#items").children("li").each(function (index, item) {
if(_this.leftHeight <= _this.rightHeight){
$l.append($(item));
_this.leftHeight = $l.height();
}else{
$r.append($(item));
_this.rightHeight = $r.height();
}
})
}
}
就此保证了,不管怎么刷新页面,数据排序都是一致的。
浙公网安备 33010602011771号