一、前言
現在寫瀑布流算不算是炒冷飯啊?
我不管, 我就要寫,誰也別想攔我。
瀑布流應該算是很常見的一種布局方法了,大致的思路也很好理解, 但是在小程序里面確有另外需要考慮的幾個問題。
問題1:uniapp是基于Vue的,所以不好直接操作DOM。
問題2:uniapp基于Vue,但也做了一些修改,所以不好拿ref來操作
二、先說思路
為了保證文章的長度,以及有些小伙伴對瀑布流的基本思路不是很了解,所以先講講瀑布流的思路,先看下圖。
可以看到,商品的圖片高度是不一致的,再加上商品標題的行數不一致,最終呈現的效果是交錯排列的。
之前在開發過程中,我也試過用CSS的Flex布局,Column布局來實現,勉強能實現同樣的效果,但是最終對接后臺要考慮商品的熱度優先,所以只能放棄。
Flex實現缺點:使用Flex布局并不能準確計算高度來插入商品。
Column實現缺點:使用Column布局不好操作先后順序。
PS:如果對產品排序沒有要求的話, 可以考慮純CSS實現,這里不多贅述,掘金里很多的。
三、核心代碼
如題,本文對于瀑布流的實現是基于uniapp開發小程序的,如果期望JS原生實現,本文的很多思路是需要修改的。
先解答部分疑惑:
因為無法通過$refs獲取到列的高度,所以代碼是通過Image標簽的@load時間先加載一次圖片,并將圖片的寬高等信息傳遞給方法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
|
// component/waterfall.vue <template> <view class= "waterfall" > <view hidden> // 用JS原生實現時可以直接用for循環插入,然后獲取列高度 // 這里通過載入圖片調用方法, 默認傳參帶有圖片信息,可以獲得圖片高度 <block v- for (item in imgList " :key=" item.id "> <image :src=" item.url " @load=" loadImg " ></iamge> </block> </view> <view class=" list " v-for=" (list, key) in waterfall " :key=" key "> <navigator url=" https: //www.baidu.com" v-for="item in list.list" :key="item.id"> <image :src="item.url " mode=" widthFix "></image> <view class=" shop-info"> /* 標題等信息,略 */ </view> </navigator> </view> </view> </template> <script> export default { // 抽出為單獨的組件,所以數據來源于父組件傳遞,也可以是當前組件請求API props: { imgList: Array }, data(){ return { lists: [], // 備份imgList用的數組,方便操作 waterfall: [ // 用于記錄當前列的高度,不在方法中保存是為了上拉獲取新數據也能使用 // 因為默認手機顯示,可以固定兩列 // 如果是做自適應或者電腦端多列,可以動態插入實現多列 { height: 0, list: [] },{ height: 0, list: [] } ] } }, created(){ this .lists = this .imgList; // Vue創建data后立即備份 }, watch(){ // 監聽數據源,如果有新值傳入,則用lists數組備份 imgList(data){ data.length && this .lists.push(...data); } }, methods: { loadImg(ev){ let Root = this .waterfall; let height = e.detail.height; // 根據當前高度決定將新數據給誰,并更新列高度;優先插入左側 if (Root[0].height <= Root[1].height){ // 考慮熱度優先的問題, 所以用的是shift()方法推出頭部數據。 Root[0].list.push( this .lists.shift()) Root[0].height += height; } else { Root[1].list.push( this .lists.shift()) Root[1].height += height; } } } } </script> |
至此,核心代碼就完成了。
PS:因為要借由image的@load事件來觸發方法,所以大量加載勢必會影響性能,所以要自己做點取舍了。
四、總結
希望如果有小伙伴看完這篇文章之后,決定使用這個方法時,能記得一件事,這個寫法可能有性能問題方面的影響,能在這方面下功夫去深入研究下。
到此這篇關于uniapp小程序實現瀑布流布局的思路與代碼的文章就介紹到這了,更多相關uniapp小程序瀑布流布局內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!
原文鏈接:https://juejin.cn/post/6947531903436062750