微信小程序实战项目(商品列表)-four
发表时间:2020-11-19
发布人:葵宇科技
浏览次数:71
Chapter four
1.商品列表效果图
2商品列表分解图
3.商品列表业务逻辑
1.加载商品列表数据
2.启用下拉页面功能
2.1.页面的json文件中开启设置enablePullDownRefresh:true
2.2.页面的js中,绑定事件onPullDownRefresh
3.启用上拉页面功能,onReachBottom页面触底事件
4.加载下一页功能
4.接口API
1.获取商品列表数据
https://api-hmugo-web.itheima.net/api/public/v1/goods/search
5.关键技术
1.小程序配置文件中启用上拉和下拉功能
1.1启用下拉功能
这个启用下拉功能用来刷新,微信小程序文档提供了刷新事件为onPullDownRefresh,首先需要在商品列表对应的页面配置进行index.json添加为 "enablePullDownRefresh": true,然后触发下拉刷新事件为onPullDownRefresh(),代码如下:
这个触发刷新事件后,就会重置数据的数组、重置页码为1、重新发送请求数据、数据请求成功回来,需要手动的关闭并等待效果。
// 下拉刷新事件
>// 关闭下拉刷新的窗口 如果没有调用下拉刷新的窗口 直接关闭也不会报错
wx.stopPullDownRefresh();
因为这种等待效果大概5秒,刷新时大概一秒就完事!所以需要去关闭等待效果。注意:刷新和等待效果是两回事。
在没关闭等待效果的情况如下:
1.2启用上拉功能
启用上拉功能可以用来分页,如果没有分页的话,想想如果数据量非常大时,然后一次性地返回所有数据给前台,那么页面的打开速度及图片加载就容易会下降。考虑到用户使用流量,如果用户只看第一页的内容,而不用看下面的内容,这样会浪费流量。所以采取启用上拉分页来作优化,当使用上拉分页的时候,后台不需要一次性返回数据给前台,如果用户需要下拉下面的内容,那就会加载中加数据的内容出来了。
实现思路原理:
当用户滚到底部的时候,开始加载下一页数据。首先找到触发上拉事件(onReachBottom),然后判断一下有没有下一页数据。首先我说一下分页页数的详细,首先获取到总页数 也就是说获取数据内容的条数,然后计算最后的总页数,比如:总页数=Math.ceil(总条数/每一页数据的行数),每一页数据的行数就是显示一页数据的多少行,比如这个显示一页数据为10行,那么它就是10,假如为Math.ceil(23/10)=3。Math.ceil就是向上取舍近整数,比如2.3取为3。然后这样获取到当前的页码,判断一下当前的页码是否大于等于总页数,如果没有下一页数据,那么到这为止,并弹出提示框;如果有下一页数据,然后来加载下一页的数据,增加当前的页码+1,重新发送请求数据并加载下一页的新数据内容,注意:如果数据请求回来,必须要对data中的数据进行拼接,而不是全部替换掉的!
1.找到触发上拉事件(onReachBottom)
2.判断有没有下一页数据
2.1首先获取总条数
计算: 总页数 = Math.ceil(总条数 / 每一页数据的行数)
2.2获取到当前的页码
2.3判断一下 当前的页码是否>=总页数
3.如果没有下一页数据,弹出一个提示框“没有下一页了”。
4.如果还有下一页数据 然后来加载下一页数据
4.1 增加当前的页码+1
4.2 重新发送请求数据并加载下一页的新数据内容
4.3 如果数据请求成功回来,要对data中的数据进行拼接
// 接口要的参数
QueryParams:{
query:"",
cid:"",
pagenum:1,
pagesize:10
},
// 总页数
totalPages:1,
/**
* 生命周期函数--监听页面加载
*/
><view class="tabs">
<view class="tabs_title">
<view
wx:for="{{tabs}}"
wx:key="id"
class="title_item {{item.isActive?'active':''}}"
bindtap="handleItemTap"
data-index="{{index}}"
>
{{item.value}}
</view>
</view>
</view>
我相信读者小程序开发的基础或Vue的基础都能看懂,什么的语法糖其实很像Vue,我说明一下这些的作用:
1.wx:for="{{tabs}}"主要是用来渲染列表,需要的是组件之外传入,也可以在js的组件中里面自定义个数组。
2.以上的循环完成之后一般需要加上wx:key="id"及data-index="{{index}}",它们主要用来唯一标识每一项,这样后面对每一项的ID进行操作,因为我们程序一般要明确知道切换每一个项的操作,而且在切换到不同项的做出对应的操作,如果没有定义这些数据,那么后面工作会bug。
3.class="{{item.isActive?'active':' '}}"主要表示已选中的某一项,当该项被选中后需要改变某颜色,比如:当active与当前项的索引isActive相等时才表示选中。
4.bindtap=“handleItemTap”表示触发点击事件,同时在js中触发并进行操作。
另外<slot>标签其实就是叫插槽,在每不同的标题栏会有不同的显示,一般在显示内容的页面,这个slot也可以控制显示与隐藏功能。
2.JS
components/Tabs/Tabs.js,这个主要是用子组件向父组件传递数据
其实原理上来说,当点击事件触发的时候,也需要触发父组件的自定义事件,这样同时传递数据给父组件。
比如:this.triggerEvent("父组件自定义事件的名称",要传递的参数)
// components/Tabs/Tabs.js
Component({
/**
* 组件的属性列表
*/
{//里面存放的是要从父组件中接收的数据
properties: {
tabs:{
type:Array,
value:[]
}
},
/**
* 组件的初始数据
*/
data: {
},
/**
* 组件的方法列表
*/
methods: {
// 1 点击事件
/*点击事件触发的时候
触发父组件中的自定义事件,同时传递数据给父组件
this.triggerEvent("父组件自定义事件的名称",要传递的参数)*/
handleItemTap(e){
//1 获取点击的索引,获取ID的值
const {index}=e.currentTarget.dataset;
//2 触发 父组件中的事件 自定义
this.triggerEvent("tabsItemChange",{index});
}
}
})
3.wxss
这是最基本的样式文件,这个很简单,详细不多说了!
/* components/Tabs/Tabs.wxss */
.tabs{}
.tabs_title{
display: flex;
padding:15rpx 0;
}
.title_item{
display: flex;
justify-content: center;
align-items: center;
flex:1;
padding:15rpx 0;
}
.active{
color:var(--themeColor);
border-bottom:5rpx solid currentColor;
}
.tabs_content{}
以上的内容,这就是子组件的Tabs。然后接下来是父组件:
接下来的是Page/goods_list/index,这是商品列表的页面。
1.WXML
Page/goods_list/index.wxml,这作为绑定标签和父组件的自定义事件,如下:
我先说说一下,我只针对slot标签的事,其他不用管,它们都是从后台数据过来的,我们根据数组的isActive用来判断点击哪个标题栏与对应的父组件向子组件传递标签和内容。
<!-- 监听自定义事件 -->
<Tabs tabs="{{tabs}}" bindtabsItemChange="handleTabsItemChange" >
<!-- 内容 -->
<block wx:if="{{tabs[0].isActive}}">
<view class="first_tab">
<navigator class="goods_item"
wx:for="{{goodsList}}"
wx:key="goods_id"
url="/pages/goos_detail/index?goods_id={{item.goods_id}}"
>
<!-- 左侧 图片容器 -->
<!-- 右侧 商品容器 -->
</navigator>
</view>
</block>
<block wx:elif="{{tabs[1].isActive}}">1</block>
<block wx:elif="{{tabs[2].isActive}}">2</block>
</Tabs>
然后子组件(components/Tabs/Tabs.wxml),slot的标签并接收到数据并显示内容。
<view class="tabs_content">
<slot></slot>
</view>
2.JS
在js父组件中的数据与自定义事件。
Page({
data: {
tabs:[
{
id:0,
value:"综合",
isActive:true
},
{
id:1,
value:"销量",
isActive:false
},
{
id:2,
value:"价格",
isActive:false
}
],
goodsList:[]
},
//标题点击事件 从子组件传递过来
handleTabsItemChange(e){
// 1 获取被点击的标题索引
const {index}=e.detail;
// 2 修改源数组
let {tabs}=this.data;
//循环数组
//[].forEach遍历数组,它在遍历数组的时候修改了v,也会导致原数组被修改
tabs.forEach((v,i)=>i===index?v.isActive=true:v.isActive=false);
// 3 赋值到data中
this.setData({
goodsList:res.goods
})
}
)}
这样搞定OK!
最终如下:
下一期就是小程序商品详情-five
不断更新中.....给知识充电中。
欢迎各位大佬评论、点赞和收藏!Thanks