一开始以为这个问题很简单,每插入一张图片以前比较各个“流”的高度,找个最短的放进去就好了。后来发现没那么简单。 直接想到的问题就是图片未加载完成是得不到图片的完整高度的,后来找到dom的naturalHeight属性,能够在图片未加载成功时就获取到图片高度html
而后开始常规操做,用nextTick递归把图片数据插入到对应的数组中,可是nextTick中获取图片dom的naturalHeight是获取不到的,可是页面中图片就算未加载完成是能够获取到的。猜测是vue渲染完图片的dom时执行nextTick,图片刚开始加载,这时候接口尚未获取到计算naturalHeight属性相关的数据。因此这条路就是走死了,由于这个方法下图片何时加载完成没法监控,都是第一张图片插入以后第二张图片放哪里无法计算。vue
第一时间想到的就是setInterval,而后不到一秒钟就被本身否决了,丑并且耗费性能,宁愿在数据库里扩展width、height字段也不用这个方法(我还真的扩展了)。可是不太服气,而后寻找尽是广告的度娘,发现一个方法,既然以前问题出在图片何时加载完成没法监控,那就用image.onload()方法获取图片信息,而后在回调里面丁零当啷一顿操做拼好dom,插入到页面中。 偷来的代码数据库
sort(j) {
if (j < this.moments.length) {
let that = this;
// 建立Image类
var newImg = new Image();
// 获取要加载的图片地址
newImg.src =
"http://lanyue.ink:8123/images/" +
(Math.floor(Math.random() * 15) + 1) +
".png";
// 图片加载完成后(异步)
newImg.onload = () => {
// 四个管道的高度
var arr = [
that.$refs.piping0.offsetHeight,
that.$refs.piping1.offsetHeight,
that.$refs.piping2.offsetHeight,
that.$refs.piping3.offsetHeight
];
//获取管道最小高度
var min = arr.indexOf(Math.min.apply(Math, arr));
// 添加卡片的模板
var html =
`<div class="card">
<img src=` + newImg.src + `>
<div>
<img src="http://lanyue.ink:8123/images/avatar.jpg" alt="">
<div>` + this.moments[j].id + " " + this.moments[j].content + `</div>
</div>
</div>`;
//给最小的管道添加卡片
if (min == 0) {
that.$refs.piping0.innerHTML += html;
} else if (min == 1) {
that.$refs.piping1.innerHTML += html;
} else if (min == 2) {
that.$refs.piping2.innerHTML += html;
} else if (min == 3) {
that.$refs.piping3.innerHTML += html;
}
that.sort(j + 1);
};
}
},
复制代码
做者若是看到了不要喷我,都走到这一步了,为何还要用插入html的方式,拿到图片的宽高,加一个计算“流”高度的字段,插入一张图就加一个图片的高度,这样也就不用再从dom中获取“流”的高度。这样的好处有两个,一是减小一次dom的查询,二是若是页面须要响应式,插入html的方式实际上是没法经过直接改变数据操做dom,违背了vue的本意(对于两个方法的性能消耗有机会多作研究,感受起来应该是个人方法美一点)。数组
getImageList() {
let that = this;
imageService.getImageList(this, {
params: {
categoryId: 37
}
}).then(function (result) {
if (result.code === 0) {
that.tempImage = result.data;
that.pushImage(0);
}
});
},
pushImage(index) {
if (index >= this.tempImage.length) return;
let img = new Image(), that = this;
img.src = that.$store.state.imageURL + that.tempImage[index].url;
img.onload = () => {
let min = that.imageHeight[0], imageIndex = 0;
that.imageHeight.forEach(function (item, _index) {
if (min > item) {
min = item;
imageIndex = _index;
}
});
that.imageHeight[imageIndex] += img.naturalHeight / img.naturalWidth;
that.imageList[imageIndex].push(that.tempImage[index]);
that.pushImage(index + 1);
}
},
复制代码
最后再加上一段监控页面位置函数,实现拉到底部加载图片的功能bash
pullDown() {
// 获取滚轮位置
this.height1 = window.pageYOffset ||
document.documentElement.scrollTop ||
document.body.scrollTop;
// 文档高度
this.height2 = document.body.scrollHeight;
// 可视区域
// 设置compatMode兼容IE
this.height3 = document.compatMode === "CSS1Compat"
? document.documentElement.clientHeight
: document.body.clientHeight;
// 若是滚动到最低(这里设置离最底还有100距离才触发函数)
// available条件是为了防止触底时一直不断地请求。所以,请求一次后available设为0,直到滚动到离底部超过100距离(即数据加载玩后)才设为1
if (this.height3 + this.height1 >= this.height2 - 100 && this.available) {
this.available = false;
//请求下一页,若是当前页等于最大页,直接返回
if (this.pagination.currentPage >= this.pagination.totalPage) {
this.footerVisible = true;
return;
}
this.pagination.currentPage++;
this.getImagePage();
} else if (this.height3 + this.height1 < this.height2 - 100) {
this.available = true;
}
}
复制代码
最终效果图 app
参考文章:来自MarieDreamer blog.csdn.net/qq_33514421…dom