07_案例二-本地生活列表页面
继续上一案例,完成点击九宫格内的对应功能,跳转到对应的详情列表页
效果图
要实现的功能:
- 页面导航并传参
- 上拉触底时加载下一页数据
- 下拉刷新列表数据
页面导航并传参
完成这一步,首先要构建一个详情列表页,将首页的九宫格组件改造成跳转标签,跳转时携带参数
在app.json文件中的pages块,添加一个"pages/shopList/shopList"
"pages":[
"pages/home/home",
"pages/message/message",
"pages/contact/contact",
"pages/shopList/shopList"
],
改造首页九宫格子组件的结构,将<view>改造成<navigator>组件,并给其添加url属性
<!-- 九宫格区域 -->
<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>
改造完成后,可以看到首页页面展示并无变化,点击美食,就跳转到shopList页面,并且参数也传递过去了。
设置页面标题
点击微信开发文档,查看截图标识部分
九宫格每个详情页虽然设计是一样的,但是标题以及要展示的内容是不一样的,我们需要在跳转到对应的详情页时,动态修改页面标题,就要使用wx.setNavigationBarTitle(Object object)方法,这个方法应该在哪里被调用?肯定是要刚一进入页面的时候调用。
请查看这里
一个页面周期函数有五个,其中onLoad是页面数据加载的时候会调用,而onReady则是页面初次渲染完成后才会调用,我们要设置页面标题,肯定是要在数据渲染完成时才去设置的。
还记得我们前面怎么动态修改页面内容吗?在js文件的data块中定义数据,然后在页面中使用,当data中的数据被修改时,页面展示会动态变化,这里为什么不是如此做?而是直接调用一个方法?因为页面标题不是我们书写的,而是系统自带的,我们没有标题数据变量,不能直接修改,只能调用wx暴露出来的修改标题接口。
onReady: function () {
},
这个onReady方法没有参数,我们想要获取标题数据,只能在onLoad方法中将页面跳转时携带的参数保存在data块中,因为onLoad方法是在onReady方法之前被系统调用。
读者可能会问,这还不是要用到data块吗?在这里我们只是用data块来间接获取页面标题数据,一旦页面渲染完成,我们再通过dataSet方法修改data中的数据,也没办法改变标题,这跟之前的动态修改页面数据是有本质区别的。
修改shopList.js文件
// 暂存页面跳转的传参
data: {
query: {}
},
// 将页面跳转的参数存储到data.query中
onLoad: function (options) {
this.setData({ query: options })
},
//修改页面标题
onReady: function () {
wx.setNavigationBarTitle({
title: this.data.query.title,
})
},
效果
之前一直是本地生活,现在成了美食,点击九宫格其他组件,同样会产生对应的改变
商铺列表页展示:
获取并渲染商铺列表数据
列表页面API接口
以分页的形式,加载指定分类下商铺列表的数据:
- 接口地址
- https://www.escook.cn/categories/:cate_id/shops
- URL 地址中的 :cate_id 是动态参数,表示分类的 Id
- 请求方式
- GET 请求
- 请求参数
- _page 表示请求第几页的数据
- _limit 表示每页请求几条数据
我们先请求数据并且测试一下。
在shopList页面的data块定义几个变量用来存放相关数据
data: {
query: {}, // 存放页面跳转时携带的参数
shopList:[], // 存放商铺列表数据
page:1, // 默认是从第1页开始
pageSize:10, // 默认是每页10条数据
total:0 // 数据总条数
},
定义方法getShopList,获取商铺列表数据,在onLoad方法中调用,完成页面加载时的数据请求
getShopList() {
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) => {
// 将数据保存到data中
this.setData({
shopList: [...this.data.shopList, ...res.data],
total: res.header['X-Total-Count'] - 0
})
}
})
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
this.setData({ query: options })
this.getShopList() //调用商铺列表数据请求方法
},
编译测试
数据请求成功
渲染数据
// wxml 部分
<view class="shop-item" wx:for="{{shopList}}" wx:key="{{id}}">
<view class="thumb">
<image src="{{item.images[0]}}"></image>
</view>
<view class="info">
<text class="shop-title">{{item.name}}</text>
<text>电话:{{item.phone}}</text>
<text>地址:{{item.address}}</text>
<text>营业时间:{{item.businessHours}}</text>
</view>
</view>
// wxss部分
.shop-item {
display: flex;
padding: 15rpx;
border: 1rpx solid #efefef;
margin: 15rpx;
border-radius: 15rpx;
box-shadow: 1rpx 1rpx 15rpx #ddd;
}
.thumb image {
width: 250rpx;
height: 250rpx;
display: block;
margin-right: 15rpx;
}
.info {
display: flex;
flex-direction: column;
justify-content: space-around;
font-size: 24rpx;
}
.shop-title {
font-weight: bold;
}
展示效果
添加loading效果,修改getShopList方法
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) => {
// 将数据保存到data中
this.setData({
shopList: [...this.data.shopList, ...res.data],
total: res.header['X-Total-Count'] - 0
})
},
complete: () => {
// loading隐藏
wx.hideLoading()
}
})
},
配置上拉触底加载下一页数据效果
配置上拉触底,修改shoplist.json文件
{
"usingComponents": {},
"onReachBottomDistance": 200 //改为上拉触底200像素触发
}
修改shoplist.js文件,在onReachBottom中监听触底事件
onReachBottom: function () {
console.log('ok');
},
编译,测试
修改onReachBottom
onReachBottom: function () {
this.setData({
page: this.data.page + 1
})
this.getShopList()
},
可以看到页面内容确实增加了,并且当前页标识page字段也在增加
给上拉事件做节流处理。因为在网速偏慢的情况下,当前页没有请求并且加载完,是不应该请求下一次的数据。
请求节流的方法,在data块中配置一个节流阀 isLoading,默认值为false,每次请求方法getShopList代码一开始执行就要先将节流阀置为true。如果不管请求成功还是失败,都将该节流阀置为false。而在上拉触底监听方法中,每次调用getShopList之前应该判断当前是否在请求数据,如果在请求数据,应该直接返回,本次不执行。
具体代码如下
// 设置节流阀
data: {
query: {}, // 存放页面跳转时携带的参数
shopList: [], // 存放商铺列表数据
page: 1, // 默认是从第1页开始
pageSize: 10, // 默认是每页10条数据
total: 0, // 数据总条数
isLoading: false // 节流阀
},
// 控制节流阀
getShopList() {
// 打开节流阀
this.setData({ isLoading: true })
//展示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) => {
// 将数据保存到data中
this.setData({
shopList: [...this.data.shopList, ...res.data],
total: res.header['X-Total-Count'] - 0
})
},
complete: () => {
// loading隐藏
wx.hideLoading()
// 关闭节流阀
this.setData({ isLoading: false })
}
})
},
// 判断节流阀
onReachBottom: function () {
// 判断节流阀
if (this.data.isLoading) return
this.setData({
page: this.data.page + 1
})
this.getShopList()
},
这个不太好演示,截图也不能展示出来,读者请自行验证
判断数据是否加载完毕
后台数据是有限的,本次案例美食下只有80条数据,每次请求10条,那我们肯定不能请求第九次,第十次吧
如果下面的公式成立,则证明没有下一页数据了
页码值 * 每页数据条数 >= 数据总条数
page * pageSize >= total
修改 onReachBottom 方法,加入数据是否加载完毕的操作
onReachBottom: function () {
if (this.data.page * this.data.pageSize >= this.data.total) {
return wx.showToast({
title: '数据加载完毕',
icon: 'none'
})
}
// 判断节流阀
if (this.data.isLoading) return
this.setData({
page: this.data.page + 1
})
this.getShopList()
},
效果
开启页面下拉刷新操作
修改shopList的json配置文件
{
"usingComponents": {},
"onReachBottomDistance": 200,
"enablePullDownRefresh": true,//开启下拉刷新
"backgroundColor": "#efefef", //修改下拉刷新的背景色
"backgroundTextStyle": "dark" //给下拉刷新添加小圆点
}
下拉刷新效果确实添加了
我们还需要在js文件中修改下拉刷新的样式,值得注意的是,在手机上调试会发现,下拉刷新不会自动关闭,下拉刷新操作需要我们手动关闭。同时我们希望下拉刷新之后重新请求数据,即,当前页码值为1。
主要修改这几处地方
onPullDownRefresh: function () {
this.setData({
page: 1, //重置页码值
shopList: [], //清空列表数据
total: 0//总数居条数清空
})
// 重新发起请求,并且传入一个回调函数
this.getShopList(()=>{wx.stopPullDownRefresh()})
},
// ------------------------------------------------------------
getShopList(cb) {//给一个cb参数,用来判断当前是否需要关闭下拉刷新
// 打开节流阀
this.setData({ isLoading: true })
//展示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) => {
// 将数据保存到data中
this.setData({
shopList: [...this.data.shopList, ...res.data],
total: res.header['X-Total-Count'] - 0
})
},
complete: () => {
// loading隐藏
wx.hideLoading()
// 关闭节流阀
this.setData({ isLoading: false })
// 关闭下拉刷新操作,因为很多地方都会调用这个请求函数,但不是所有的请求数据场景下都需要关闭下来刷新操作,只有在下拉刷新时才需要调用
cb && cb()
}
})
},
真机测试不好截图,读者请自行验证
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了