小程序瀑布流布局

 

实现方案
左右两边是两列,两个数组,用boundingClientRect获取左右的高度,判断下一个应该添加到哪个数组,接口用的豆瓣公共的接口,用scroll-view实现下拉刷新上拉加载更多
wxml片段:

 1 <block wx:if="{{!isNoData}}">
 2   <view class="pro-box">
 3     <view
 4     id="leftList"
 5     class="pro-list pro-list1">
 6       <view
 7       wx:for="{{leftList}}"
 8       wx:key="id"
 9       class="pro-item">
10         <image class="img" mode="widthFix" src="{{item.pic}}"></image>
11         <view class="title">{{item.title}}</view>
12         <view class="ft">
13           <view class="price">
14             <text class="pre"></text>{{item.minPric}}
15           </view>
16           <view class="num">{{item.minNum}}{{item.unit}}起批</view>
17         </view>
18       </view>
19     </view>
20     <view
21     id="rightList"
22     class="pro-list pro-list2">
23       <view
24       wx:for="{{rightList}}"
25       wx:key="id"
26       class="pro-item">
27         <image class="img" mode="widthFix" src="{{item.pic}}"></image>
28         <view class="title">{{item.title}}</view>
29         <view class="ft">
30           <view class="price">
31             <text></text>{{item.minPric}}
32           </view>
33           <view class="num">{{item.minNum}}件起批</view>
34         </view>
35       </view>
36     </view>
37   </view>
38   <mp-loading wx:if="{{isLoading}}" ext-class="loading" type="circle"></mp-loading>
39   <view wx:if="{{isComplete}}" class="no-more">没有更多数据了</view>
40 </block>
41 <view wx:else class="no-data">暂无<text class="keyword">{{formData.keyWord}}</text>数据~</view>

 

js代码片段:

  1 import { get } from '../../../../api/http.js'
  2 import { showFail } from '../../../../utils/public.js'
  3 const app = getApp()
  4 let leftHeight = 0
  5 let rightHeight = 0
  6 Page({
  7 
  8   /**
  9    * 页面的初始数据
 10    */
 11   data: {
 12     isLoading: false, // 列表是否正在加载更多
 13     isComplete: false, // 列表是否所有数据都加载完成
 14     isNoData: false, // 列表是否没有数据
 15     curPage: 1, // 列表当前页
 16     pageSize: 20, // 列表每页显示多少条
 17     leftList: [],
 18     rightList: []
 19   },
 20 
 21   // 获取列表
 22   getList () {
 23     const that = this
 24     const curPage = that.data.curPage
 25     const pageSize = that.data.pageSize
 26     const keyWord = ''
 27     let isShowLoading = true
 28 
 29     // 第一页的loading采用http封装里面的loading,其他采用本页中的isLoading
 30     if (curPage !== 1) {
 31       isShowLoading = false
 32       that.setData({
 33         isLoading: true
 34       })
 35     }
 36 
 37     get('/api/shop/queryListCompany', {
 38       data: {
 39         page: curPage,
 40         pageSize,
 41         keyword: keyWord
 42       },
 43       isShowLoading: isShowLoading
 44     }).then(async (res)=> {
 45       // 请求完成后隐藏loading
 46       that.setData({
 47         isLoading: false
 48       })
 49       if (res.code === '1') {
 50         const result = res.data
 51         const dataArry = result.data || []
 52         const totalPage = result.totalPage
 53         const total = result.totalCount
 54         const leftList = that.data.leftList
 55         const rightList = that.data.rightList
 56 
 57         // 当返回总条数为0时说明没有数据
 58         if (total === 0) {
 59           that.setData({
 60             isNoData: true
 61           })
 62           return
 63         }
 64 
 65         if (curPage > totalPage) {
 66           that.setData({
 67             isComplete: true
 68           })
 69           return
 70         }
 71 
 72         for (const item of dataArry.values()) {
 73           const itemObj = {
 74             id: item.id,
 75             pic: app.globalData.fileUrl + item.authPic,
 76             title: item.companyName,
 77             minPric: '35.00',
 78             minNum: 99,
 79             unit: '件'
 80           }
 81           if (leftHeight <= rightHeight) {
 82             leftList.push(itemObj)
 83           } else {
 84             rightList.push(itemObj)
 85           }
 86           await that.getBoxHeight(leftList, rightList)
 87         }
 88         // 请求完成后隐藏loading
 89         that.setData({
 90           curPage: curPage + 1
 91         })
 92       } else {
 93         showFail(res.msg)
 94       }
 95     }).catch((error) => {
 96       // 请求完成后隐藏loading
 97       that.setData({
 98         isLoading: false
 99       })
100       showFail()
101     })
102   },
103 
104   //获取左右两边高度
105   getBoxHeight (leftList, rightList) {
106     const that = this
107     return new Promise((resolve) => {
108       that.setData({
109         leftList,
110         rightList
111       }, () => {
112         let query = wx.createSelectorQuery().in(that)
113         query.select('#leftList').boundingClientRect()
114         query.select('#rightList').boundingClientRect()
115         query.exec((res) => {
116           if (res[0]) {
117             leftHeight = res[0].height
118             rightHeight = res[1].height
119           }
120           resolve()
121         })
122       })
123     })
124   },
125 
126   /**
127    * 生命周期函数--监听页面加载
128    */
129   onLoad: function (options) {
130     this.getList()
131   },
132 
133   /**
134    * 生命周期函数--监听页面初次渲染完成
135    */
136   onReady: function () {
137 
138   },
139 
140   /**
141    * 生命周期函数--监听页面显示
142    */
143   onShow: function () {
144 
145   },
146 
147   /**
148    * 生命周期函数--监听页面隐藏
149    */
150   onHide: function () {
151 
152   },
153 
154   /**
155    * 生命周期函数--监听页面卸载
156    */
157   onUnload: function () {
158 
159   },
160 
161   /**
162    * 页面相关事件处理函数--监听用户下拉动作
163    */
164   onPullDownRefresh: function () {
165 
166   },
167 
168   /**
169    * 页面上拉触底事件的处理函数
170    */
171   onReachBottom: function () {
172     const that = this
173     if (that.data.isLoading || that.data.isComplete || that.data.isNoData) {
174       return
175     }
176     that.getList()
177   },
178 
179   /**
180    * 用户点击右上角分享
181    */
182   onShareAppMessage: function () {
183 
184   }
185 })

 

wxss文件:

 1 .pro-box{width: 690rpx;margin: 0 auto;padding-top: 75rpx;overflow: hidden;}
 2 .pro-list,.pro-item .img{width: 335rpx;overflow: hidden;}
 3 .pro-list1{float: left;}
 4 .pro-list2{float: right;}
 5 .pro-item{margin-top: 30rpx;}
 6 .pro-item .img{border-radius: 16rpx;}
 7 .pro-item .title{color: #333;font-size: 30rpx;font-weight: bold;line-height: 42rpx;margin-left: 10rpx;margin-right: 10rpx;}
 8 .pro-item .ft{display: flex;align-items: center;}
 9 .pro-item .price{color: #E94F5A;font-size: 36rpx;font-weight: bold;margin-right: 30rpx;}
10 .pro-item .price .pre{font-size: 24rpx;position: relative;top: -2rpx;}
11 .pro-item .num{color: #999;font-size: 26rpx;}
12 
13 .loading .weui-loadmore,.no-more{margin-bottom:0;margin-top: 20rpx;padding-bottom: 20rpx;}
14 .loading .weui-loadmore__tips,.no-more{font-size: 30rpx;color: #aaa;text-align: center;}
15 .no-data{text-align: center;color: #aaa;padding:50rpx;font-size: 30rpx;}
16 .no-data .keyword{color: #E94F5A;}

 

参考文献:

1、小程序瀑布流布局(完美方案)  

2、vue瀑布流布局(完美方案)

3、小程序瀑布流布局

posted @ 2022-09-01 15:47  明天不上班啊  阅读(1888)  评论(0)    收藏  举报