「这是我参与2022首次更文挑战的第15天,活动详情查看:2022首次更文挑战」
demo实践
在小程序demo实践(一)里已经做了首页效果及实现步骤,具体如下:
- 梳理项目结构
- 配置导航栏效果
- 配置tabBar效果
- 实现轮播图效果
- 实现九宫格效果
- 实现图片布局
商铺列表及实现步骤
本篇主要讲商铺列表的效果及实现步骤
- 页面导航并传参
- 列表页面的API请求
- 上拉底部时加载下一页数据
- 下拉刷新列表数据
- 使用
wxs处理手机号
页面导航并传参
-
创建商铺列表页面
"pages":[ "pages/home/home", "pages/message/message", "pages/contact/contact", "pages/shopList/shopList" ], -
将九宫格
view改造成navigator,点击九宫格的每一项将相应的值从首页传到商铺列表页<view class="grid-list"> <navigator class="grid-item" wx:for="{{gridList}}" wx:key="id" url="/pages/shopList/shopList?id={{item.id}}&title={{item.name}}" > <image src="{{item.icon}}"></image> <text>{{item.name}}</text> </navigator> </view> -
设置商铺页面的标题
设置标题有俩种方式
-
在
.json文件中设置页面标题,这种方式设置标题是不可以修改的{ "usingComponents": {}, "navigationBarTitleText": "美食" } -
动态设置标题,通过 API 设置(动态设置标题需要在生命周期函数的
onReady()中调用)wx.setNavigationBarTitle({ title: this.data.query.title })
设置页面标题
Page({ //定义一个全局变量 data: { query:{} }, //读取传参,并转存全局变量 onLoad: function (options) { this.setData({ query:options }) }, //设置标题 onReady: function () { wx.setNavigationBarTitle({ title: this.data.query.title, }) } }) -
列表页面的分页API请求
以分页的形式,加载指定分类下的商铺列表的数据
- 接口地址
- www.escook.cn/categories/…
- url 地址中的
:cate_id为动态参数,表示分类的id
- 请求方式
- GET 请求
- 请求参数
-
_page 表示请求第几页的数据
-
_limit 表示每页请求几条数据
-
页面数据
Page({
data: {
query:{},
//商铺列表
shopList:[],
//分页码
page:1,
//分页下载量
pageSize:10,
//总条数
total:0
},
getShopList(){
//添加loading框
wx.showLoading({
title: '数据加载中...',
})
wx.request({
url: `https://www.escook.cn/categories/${this.data.query.id}/shops`,
method: "GET",
data: {
_page:this.data.page,
_limit:this.data.pageSize
},
success: (res) => {
console.log(res)
this.setData({
shopList:[...this.data.shopList,...res.data],
total: res.header["X-Total-Count"] - 0
})
},
complete: () => {
wx.hideLoading()
}
})
},
onLoad: function (options) {
this.setData({
query:options
})
//下载商铺列表
this.getShopList()
},
onReady: function () {
wx.setNavigationBarTitle({
title: this.data.query.title,
})
}
})
页面结构
<view class="shop-item" wx:for="{{shopList}}" wx:key="id">
<view class="tumb">
<image src="{{item.images[0]}}"></image>
</view>
<view class="info">
<text class="shopTitle">{{item.name}}</text>
<text>电话:{{item.phone}}</text>
<text>地址:{{item.address}}</text>
<text>营业时间:{{item.businessHours}}</text>
</view>
</view>
页面美化
.shop-item {
display: flex;
padding: 15rpx;
border: 1rpx solid #efefef;
border-radius: 9rpx;
margin: 15rpx;
box-shadow: 1rpx 1rpx 15rpx #dddddd;
}
.tumb image {
width: 250rpx;
height: 250rpx;
display: block;
margin-right: 15rpx;
}
.info {
display: flex;
flex-direction: column;
justify-content: space-around;
font-size: 24rpx;
}
.shopTitle {
font-weight: bold;
}
上拉底部时加载下一页数据
-
设置上拉触底的距离
在商铺页面的
.json文件中设置触底距离{ "usingComponents": {}, "onReachBottomDistance": 200 } -
上拉触底事件中,分页码自增。再次调用下载商铺信息的接口
onReachBottom: function () { this.setData({ page: this.data.page + 1 }) this.getShopList() }, -
通过节流阀,控制频繁、反复的上拉刷新
data: { //其他属性。。。 //定义请求节流阀 isloading:false }, getShopList(){ //变更节流阀状态 this.setData({ isloading: true }) //添加loading框 wx.showLoading({ title: '数据加载中...', }) wx.request({ //其他代码。。 complete: () => { wx.hideLoading() //变更节流阀状态 this.setData({ isloading: false }) } }) }, onReachBottom: function () { //判断节流阀状态 if (this.data.isloading) return this.setData({ page: this.data.page + 1 }) this.getShopList() }, -
判断是否还有下一页数据
服务器返回数据总数是80条,如果不做处理,继续执行上拉刷新,那么服务器每次返回的数据为空,为了解决不必要的请求,可以根据数据总数判断是否继续执行数据请求
公式:
页码值 * 每页显示多少条数据 >= 总数据条数判断是否是有下一页数据并弹框说明(调用系统
wx.showToast())onReachBottom: function () { if (this.data.isloading) return if (this.data.page * this.data.pageSize >= this.data.total){ //证明没有下一页了 return wx.showToast({ title: '数据加载完毕!', icon: "none" }) } }
下拉刷新列表数据
-
设置页面支持下拉刷新
在商铺页面的
.json文件中设置触底距离{ "usingComponents": {}, "onReachBottomDistance": 200, "enablePullDownRefresh": true, "backgroundColor": "#efefef", "backgroundTextStyle": "dark" } -
下拉刷新事件中,重置某些关键值。再次调用下载商铺信息的接口
onPullDownRefresh: function () { //重置数据值 this.setData({ page: 1, shopList: [], total:0 }) //重新发请求 this.getShopList() }, -
下拉刷新之后,关闭下拉刷新的状态
- 通过给
getShopList()函数设置回调,判断关闭下拉刷新
- 通过给
getShopList(cb){
//其他代码。。。
//请求完成
complete: () => {
wx.hideLoading()
this.setData({
isloading: false
})
cb && cb()
}
}
onPullDownRefresh: function () {
this.setData({
page: 1,
shopList: [],
total:0
})
//重新请求是将回调函数传入
this.getShopList(() => {
//停止下拉刷新
wx.stopPullDownRefresh()
})
},
使用 wxs 处理手机号
-
新建
.wxs文件//将手机号格式 13910733521 改为 139-1073-3521 function splitPhone(str){ //判断手机号是否是11位 if (str.length != 11) return str var arr = str.split("") arr.splice (3,0,"-") arr.splice (8,0,"-") return arr.join("") } //导出 module.exports = { splitPhone:splitPhone } -
页面调用
<view class="shop-item" wx:for="{{shopList}}" wx:key="id"> <view class="tumb"> <image src="{{item.images[0]}}"></image> </view> <view class="info"> <text class="shopTitle">{{item.name}}</text> <text>电话:{{tools.splitPhone(item.phone)}}</text> <text>地址:{{item.address}}</text> <text>营业时间:{{item.businessHours}}</text> </view> </view> <!-- 导入tools --> <wxs src="../../utils/tools.wxs" module="tools"></wxs>