一開始以爲這個問題很簡單,每插入一張圖片以前比較各個「流」的高度,找個最短的放進去就好了。後來發現沒那麼簡單。 直接想到的問題就是圖片未加載完成是得不到圖片的完整高度的,後來找到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