一、商品列表数据与页面分析
- 首先看下我们预期的效果:
- 需要用到之前的自定义组件SearchInput还需要自己再次定义一个组件Tabs
- Tabs分为上方的title和下方的内容,在内容中放入插槽,然后将请求的数据放入到插槽中
- 信息填充完毕,需要完成上拉加载下一页、下拉刷新、全局正在加载toast的功能
二、获取分类id
- 首先我们需要知道从何进入商品列表页面的
- 我们是从商品分类页面,通过点击不同的商品分类,进入不同的商品列表页面的
- 在这个跳转过程中,需要传递不同参数才能做到进入不同的商品列表页面
- 传什么参数呢?
- 查看接口文档,看看需要的参数
- 而参数应该是从商品分类列表传递过去的,那么看看应该传递哪个参数
- 此时,确定了我们需要的参数
cid
应该是从商品分类传递来的cat_id
- 跳转页面时,传递参数:
- 我们可以在微信开发者工具中查看传递的参数:
三、实现搜索框和tabs组件
- 搜索框直接使用之前定义的SearchInput组件就可以了
- 定Tabs组件
Tabs.wxml:
<view class="tabs">
<view class="tabs_title">
<view class="title_item"
wx:for="{{tabs}}"
wx:key="id"
class="title_item {{item.isActive ? 'active' : ''}}"
bindtap="handleItemTap"
data-index="{{index}}">
{{item.value}}
</view>
</view>
<view class="tabs_content">
<slot></slot>
</view>
</view>
Tabs.wxss:
.tabs {
}
.tabs_title {
display: flex;
}
.title_item {
display: flex;
flex: 1;
justify-content: center;
align-items: center;
padding: 15rpx 0;
}
.active{
color: var(--themeColor);
border-bottom: 5rpx solid currentColor;
}
.tabs_content {
}
Tabs.js:
Component({
properties: {
tabs: {
type: Array,
value: []
}
},
methods: {
// 点击事件
handleItemTap(e) {
// 1 获取点击索引
const { index } = e.currentTarget.dataset;
// 2 触发父组件中的事件
this.triggerEvent("tabsItemChange", { index });
}
}
})
- 该组件接收传递过来的tabs参数作为标题栏,并且监听了点击事件,定义了isActive属性判断当前活跃的标题栏,并传出该标题索引,可以在外部使用时,填充到该标题栏下的插槽中。
- 在使用时,我们只填充了综合栏目中的数据:
四、静态样式
goods_list/index.wxml:
<SearchInput></SearchInput>
<!-- 监听自定义事件 -->
<Tabs tabs="{{tabs}}" bind:tabsItemChange="handleTabsItemChange">
<block wx:if="{{tabs[0].isActive}}">
<view class="first_tab">
<navigator
class="goods_item"
wx:for="{{goodsList}}"
wx:key="goods_id">
<!-- 左侧 图片容器 -->
<view class="goods_img_wrap">
<image mode="widthFix" src="{{item.goods_small_logo ? item.goods_small_logo : 'https://ww1.sinaimg.cn/large/007rAy9hgy1g24by9t530j30i20i2glm.jpg'}}"></image>
</view>
<!-- 右侧 商品容器 -->
<view class="goods_info_wrap">
<view class="goods_name">{{item.goods_name}}</view>
<view class="goods_price">¥{{item.goods_price}}</view>
</view>
</navigator>
</view>
</block>
<block wx:elif="{{tabs[1].isActive}}">1</block>
<block wx:elif="{{tabs[2].isActive}}">2</block>
</Tabs>
goods_list/index.less:
.first_tab {
.goods_item {
display: flex;
border-bottom: 2rpx solid #ccc;
.goods_img_wrap{
flex: 2;
display: flex;
justify-content: center;
align-items: center;
image{
width: 70%;
}
}
.goods_info_wrap {
flex: 3;
display: flex;
flex-direction: column;
justify-content: space-around;
.goods_name {
display: -webkit-box;
overflow: hidden;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
}
.goods_price {
color: var(--themeColor);
font-style: 32rpx;
}
}
}
}
- 此时就将我们的页面静态内容搭建好了:
五、上拉加载下一页数据
-
用户上拉页面 滚动条触底 开始加载下一页数据
- 找到滚动条触底事件=>微信小程序官方的开发文档
- onReachBottom()
- 监听用户上拉触底事件。
- 可以在app.json的window选项中或页面配置中设置触发距离onReachBottomDistance。
- 在触发距离内滑动期间,本事件只会被触发一次。
-
判断还有没有下一页数据
- 获取到总页数 只有总条数
总页数 = Math.ceil( 总条数 / 页容量pagesize ) = Math.ceil( 23 / 10 ) = 3
- 获取当前页码 pagenum
- 判断一下 当前页码是否 大于等于 总页数
-
假如没有下一页数据=>弹出一个提示
-
假如还有下一页数据=>来加载下一页数据
1 当前的页码++
2 重新发送请求
3 数据请求回来 要对data中的数组进行 拼接 而不是全部替换!
- 获取商品数据:
async getGoodsList() {
const res = await request({url:"/goods/search", data:this.QueryParams})
// 获取总条数
const total = res.total;
// 计算总页数
this.totalPages = Math.ceil(total / this.QueryParams.pagesize);
this.setData({
// 拼接了数组
goodsList: [...this.data.goodsList, ...res.goods]
})
// 关闭下拉刷新的窗口 如果没有调用下拉刷新窗口 直接关闭也不会报错
wx.stopPullDownRefresh();
}
- 页面上拉加载:
onReachBottom() {
// 1 判断还有没有下一页数据
if (this.QueryParams.pagenum >= this.totalPages) {
// 没有下一页数据
wx.showToast({
title: '没有下一页数据了',
icon: 'none'
});
} else {
// 还有下一页数据
this.QueryParams.pagenum++;
this.getGoodsList();
}
}
六、下拉刷新
- 先在json文件中添加配置项:
"enablePullDownRefresh": true
- 再设置一下下拉时的背景:
"backgroundTextStyle": "dark"
- 下拉刷新:
// 下拉刷新事件
onPullDownRefresh() {
// 1.重置数组
this.setData({
goodsList: []
})
// 2.重置页码
this.QueryParams.pagenum = 1;
// 3.发送请求
this.getGoodsList();
//
}
七、添加全局正在加载中图标效果
- 我们每次加载的时候都显示一个加载中的图标,可以在发送请求request中添加该功能。
- 因为首页中有三个异步请求同时发出,但是如果某个请求完成就会关闭图标,所以定义一个计数器,当所有请求都完成后,才关闭图标。
八、功能测试
- 上拉加载更多:
- 下拉刷新页面: