前言
在日常开发业务中,一个典型的场景就是数据展示页面,比如下图所显示的业务场景。
这是一个微信小程序开发的项目,主要功能是闲置物品的展示,这里涉及到瀑布流,上拉刷新、下拉加载、切换分类几个功能,本文主要是梳理在此需求的开发过程中的重点。
思路与代码整理
//js
Page({
leftHight: 0, // 记录瀑布流左边的高度
rightHight: 0, // 记录瀑布流右边的高度
limit:10, // 每一次请求的数量
page:1, // 记录当前页数
data:{
loading:true, // 显示加载
isNoData:false, // 是否当前没有数据
goodClassList:[], // 导航列表
goodClassChooseIndex:0, // 导航显示的位置,默认显示第一个【推荐】
leftList: [], // 瀑布流左边的数据,
rightList: [], // 瀑布流右边的数据
isEnd:false, // 是否请求完所有的数据
},
// 获取闲置数据
async _getUnusedData(){
return new Promise(async (resolve,reject)=>{
try {
// 下面这行的getList是请求后端数据的接口,随便写的一个, 非本文上下文的代码,仅作示例
let promise = getList({
type_id:this.data.goodClassList[this.data.goodClassChooseIndex - 1].id
skip:this.limit * (this.page -1) ,
limit:this.limit
})
let res = await promise
var allData = res.result.list;
this.data.isEnd = allData.length < this.limit
//定义两个临时的变量来记录左右两栏的高度,避免频繁调用setData方法
var leftH = this.leftHight;
var rightH = this.rightHight;
var leftData = [];
var rightData = [];
for (let i = 0; i < allData.length; i++) {
allData[i].height = height
allData[i].width = width
// 下面的 335 是瀑布流每一个item的宽度,根据需要设置
let currentItemHeight = parseInt(Math.round(allData[i].height * 335 / allData[i].width));
allData[i].height = currentItemHeight + "rpx"; //因为xml文件中直接引用的该值作为高度,所以添加对应单位
if (leftH == rightH || leftH < rightH) { //判断左右两侧当前的累计高度,来确定item应该放置在左边还是右边
leftData.push(allData[i]);
leftH += currentItemHeight;
} else {
rightData.push(allData[i]);
rightH += currentItemHeight;
}
}
//更新左右两栏的数据以及累计高度
this.leftHight = leftH
this.rightHight = rightH
let obj = {
isEnd:this.data.isEnd,
isNoData:leftH + rightH === 0
}
if(this.page == 1){
this.setData(Object.assign(obj,{
leftList: [leftData],
rightList: [rightData],
}))
}else{
this.setData(Object.assign(obj,{
[`leftList[${this.page - 1}]`]: leftData,
[`rightList[${this.page - 1}]`]: rightData,
}))
}
this.page++
resolve()
} catch (error) {
reject(error)
}
})
},
// 重置页面数据
resetData(){
this.page = 1
this.data.leftList = []
this.data.rightList = []
this.leftHight = 0
this.rightHight = 0
this.data.isEnd = false
},
// 切换tab分类
chooseGoodClass(e){
let {index} = e.detail
// 避免点击相同的分类
if(index == this.data.goodClassChooseIndex) return
// 展示loading效果
this.showLoading()
// 主要因为setData是异步的,直接这么写可以同步改变data中的代码(但是不会触发渲染,只有setData方法改变数据才会触发渲染,这里主要是为了方便后面的逻辑可以使用这里的数据)
this.data.goodClassChooseIndex = index
// 重置页面数据
this.resetData()
this._getUnusedData().then(res=>{
// 关闭加载效果
this.hideLoaidng()
})
// 这个setData其实也可以放在上一步_getUnusedData的setData一起放
this.setData({
goodClassChooseIndex:index
})
},
// 下拉刷新
onPullDownRefresh: function () {
// 重置页面数据
this.resetData()
this._getUnusedData().then(res=>{
wx.stopPullDownRefresh()
})
},
// 上拉触底加载更多数据(下一页数据)
onReachBottom: function () {
// 如果已经请求完所有数据,不再发起请求
if(this.data.isEnd) return
Toast.loading({
message: '加载中...',
forbidClick: true,
duration:0
});
this._getUnusedData().then(res=>{
Toast.clear()
})
},
showLoading(){
this.setData({
loading:true
})
},
hideLoaidng(){
this.setData({
loading:false
})
}
})
下面是一些主要的wxml代码,主要提供思路
// 加载组件
<loading wx:if="{{loading}}"></loading>
// 空数据组件
<view wx:if="{{isNoData}}" class="no-data">
<no-data></no-data>
</view>
// 列表展示
<view class='lists'>
<view class='left'>
<block wx:for="{{leftList}}" wx:key="_id" wx:for-item="leftdatas">
<block wx:for="{{leftdatas}}">
<view class="list-item">
这里是商品内容
</view>
</block>
</block>
</view>
<view class='right'>
<block wx:for="{{rightList}}" wx:key="_id" wx:for-item="rightdatas">
<block wx:for="{{rightdatas}}">
<view class="list-item">
这里是商品内容
</view>
</block>
</block>
</view>
</view>
上面就是这个商品列表页面需求一个完整的实现梳理,主要是自己在做项目的过程中常常遇到这样的需求,但是没有系统的整理过,每一次都要思考一会才能去下手,这次趁着这个机会做一个整理,也是给自己以后的开发做一个记录和参考。
这里的代码可能不全,主要是提供一个思路~