一、本节项目预备知识
1、组件生命周期
1.1、什么是生命周期
生命周期(Life Cycle)是指一个对象从创建-->运行-->销毁的整个阶段,强调的是一个时间段
我们可以把每个uniapp应用运行的过程,也概括为生命周期
-
小程序的启动,表示生命周期的开发
-
小程序的关闭,表示生命周期的结束
1.2、生命周期的分类
在uniapp中,生命周期分为两类,分别是
-
应用生命周期
特指uniapp应用从启动->运行->销毁的过程。
-
页面生命周期
特指uniapp中,每个页面从加载->渲染->销毁的过程
其中,页面的生命周期范围较小,应用程序的生命周期范围较大
1.3、什么是生命周期函数
生命周期函数:是由uniapp框架提供的内置函数,会伴随着生命周期,自动按次序执行。
生命周期函数的作用:允许程序员在特定的时间点,执行某些特定的操作,例如:页面刚加载的时候,可以在onLoad生命周期函数中初始化页面的数据。
注意:生命周期强调的是时间段,生命周期函数强调的是时间点。
1.4、应用生命周期函数
uniapp的应用生命周期函数需要在App.vue中声明
函数名 | 说明 |
---|---|
onLaunch | 当uni-app 初始化完成时触发(全局只触发一次) |
onShow | 当 uni-app 启动,或从后台进入前台显示 |
onHide | 当 uni-app 从前台进入后台 |
onError | 当 uni-app 报错时触发 |
onPageNotFound | 页面不存在监听函数 |
onThemeChange | 监听系统主题变化 |
javascript
export default {
onLaunch: function() {
console.log('App Launch')
},
onShow: function() {
console.log('App Show')
},
onHide: function() {
console.log('App Hide')
}
}
1.6、页面声明周期函数
函数名 | 说明 |
---|---|
onLoad | 监听页面加载,其参数为上个页面传递的数据,参数类型为 Object(用于页面传参) |
onShow | 监听页面显示。页面每次出现在屏幕上都触发,包括从下级页面点返回露出当前页面 |
onReady | 监听页面初次渲染完成。注意如果渲染速度快,会在页面进入动画完成前触发 |
onHide | 监听页面隐藏 |
onUnload | 监听页面卸载 |
onResize | 监听窗口尺寸变化 |
onPullDownRefresh | 监听用户下拉动作,一般用于下拉刷新,参考示例 |
onReachBottom | 页面滚动到底部的事件(不是scroll-view滚到底),常用于下拉下一页数据。具体见下方注意事项 |
onTabItemTap | 点击 tab 时触发,参数为Object,具体见下方注意事项 |
onShareAppMessage | 用户点击右上角分享 |
onPageScroll | 监听页面滚动,参数为Object |
onNavigationBarButtonTap | 监听原生标题栏按钮点击事件,参数为Object |
onBackPress | 监听页面返回,返回 event = {from:backbutton、 navigateBack} ,backbutton 表示来源是左上角返回按钮或 android 返回键;navigateBack表示来源是 uni.navigateBack ;详细说明及使用:onBackPress 详解。支付宝小程序只有真机能触发,只能监听非navigateBack引起的返回,不可阻止默认行为。 |
onNavigationBarSearchInputChanged | 监听原生标题栏搜索输入框输入内容变化事件 |
onNavigationBarSearchInputConfirmed | 监听原生标题栏搜索输入框搜索事件,用户点击软键盘上的"搜索"按钮时触发。 |
onNavigationBarSearchInputClicked | 监听原生标题栏搜索输入框点击事件(pages.json 中的 searchInput 配置 disabled 为 true 时才会触发) |
onShareTimeline | 监听用户点击右上角转发到朋友圈 |
onAddToFavorites | 监听用户点击右上角收藏 |
2、页面导航
2.1、什么是页面导航
页面导航就是页面之间的相互跳转
2.2、实现页面导航的方式
-
声明式导航:navigator标签来进行跳转
-
编程式导航:uniapp提供的跳转api来实现跳转
2.3、声明式导航
1)导航到tabBar页面
在使用<navigator>
组件跳转到指定的tabBar页面时,需要指定url属性和open-type属性
-
url表示要跳转的页面地址,必须以
/
开头 -
open-type表示跳转的方式,必须是switchTab
javascript
<navigator url="/pages/home/index" open-type="switchTab">
跳转主页
</navigator>
2)导航到应用内页面
在使用<navigator>
组件跳转到指定的普通页面时,需要指定url属性和open-type属性
-
url表示要跳转的页面地址,必须以
/
开头 -
open-type表示跳转的方式,必须是navigate
javascript
<navigator url="/pages/list/index" open-type="navigate">
跳转到info页面
</navigator>
3)后退导航
如果要后退到上一页或者多级页面,则需要指定open-type属性和delta属性
-
open-type的值必须是naviateBack,表示要进行后退导航
-
delta的值必须是数字,表示要后退的层次
javascript
<navigator delta="1" open-type="navigateBack">
返回上一层
</navigator
重定向页面:redirect,跳转到指定页面,当前页面就会销毁,无法返回,只能首页按钮
2.4、编程式导航
1) 导航到 tabBar 页面
调用uni.switchTab(Object object)方法,可以跳转到tabBar页面,其中Object参数对象的属性如下
属性 | 类型 | 是否必须 | 说明 |
---|---|---|---|
url | string | 类型 | 需要跳转的tabBar页面的路径,路径后不能带参数 |
success | function | 否 | 接口调用成功的回调函数 |
fail | function | 否 | 接口调用失败的回调函数 |
complete | function | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
案例代码
javascript
//页面结构
<button type="primary" bindtap="goCategroy">跳转到分类页面</button>
//通过编程式导航,跳转到分类页面
goCategroy(){
uni.switchTab({
url: '/pages/category/category',
})
}
2) 导航到应用内页面
调用uni.navigateTo(Object object)方法,可以跳转到应用内的页面,其中Object参数对象的属性列表如下:
属性 | 类型 | 是否必须 | 说明 |
---|---|---|---|
url | string | 类型 | 需要跳转的应用内页面的路径,路径后不能带参数 |
success | function | 否 | 接口调用成功的回调函数 |
fail | function | 否 | 接口调用失败的回调函数 |
complete | function | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
javascript
//页面结构
<button type="primary" bindtap="goProductList">跳转商品列表页面</button>
//通过编程式导航,跳转到商品列表页面
goProductList(){
uni.navigateTo({
url: '/pages/product/productlist',
})
}
3) 后退导航
调用uni.navigateBack(Object object)方法,可以返回上一页或者多级页面,其中Object参数对象可选的属性列表如下
属性 | 类型 | 是否必须 | 说明 |
---|---|---|---|
delta | number | 否 | 返回的页面数,如果delta大于现有页面数,则返回到首页 |
success | function | 否 | 接口调用成功的回调函数 |
fail | function | 否 | 接口调用失败的回调函数 |
complete | function | 否 | 接口调用结束的回调函数(调 |
javascript
//页面结构
<button bindtap="gotoBack">后退</button>
//通过编程式导航
gotoBack(){
uni.navigateBack();
}
3、导航传参
3.1、声明式导航传参
navigator组件的url属性用来指定将要跳转的页面的路径。同时,路径的后面还可以携带参数
-
参数与路径之间使用?分隔
-
参数键与参数值使用=相连
-
不同参数用&分隔
代码如下所示
javascript
<navigator url="/pages/product/productlist?name=giles&age=38" open-type="navigate">跳转到购物页面</navigator>
3.2、编程式导航传参
调用uni.navigateTo(Object object)方法跳转页面时,也可以携带参数,代码如下
javascript
goProductList(){
uni.navigateTo({
url: '/pages/product/productlist?name=Giles&age=38',
})
}
3.3、接收导航参数
通过声明式导航传参或者编程式导航传参所携带的参数,可以直接在onLoad事件中直接获取到
javascript
onLoad: function (options) {
}
二、商品列表
1、点击三级分类跳转到商品列表
javascript
<view class="cate-lv3-item"
v-for="(subitem,subIndex) in item.children"
:key="subIndex"
@click="goGoodsList(subitem.cat_id)">
<image :src="subitem.cat_icon" class="item3_img"></image>
<text>{{subitem.cat_name}}</text>
</view>
定义事件处理函数如下
javascript
goGoodsList(cid){
uni.navigateTo({
url:`/pages/products/productList?cid=${cid}`
})
}
2、定义请求参数对象
我们要根据接口的要求,事先定义一个请求参数对象
javascript
data() {
return {
queryObj:{
//查询的关键字
query:'',
//查询的分类id
cid:'',
//页面值
pagenum:1,
//每页显示多少条记录
pagesize:10
}
}
}
将页面跳转时携带的参数,转存到queryObj对象中
javascript
onLoad(options) {
this.queryObj.cid=options.cid
}
3、获取商品列表数据
在data中定义数据
javascript
data(){
return{
goodsList: [],
total: 0,
}
}
在 onLoad
生命周期函数中,调用 getGoodsList
方法获取商品列表数据:
javascript
onLoad(options) {
this.queryObj.cid = options.cid
this.getProductList()
}
声明 getGoodsList
方法如下:
javascript
async getProductList() {
let result = await this.$request({
url: '/goods/search',
data: this.queryObj
})
console.log(result.message.goods);
this.goodsList = result.message.goods
this.total = result.message.total
}
渲染列表结构
javascript
<view class="goods-list">
<view class="goods-item" v-for="(item,index) in goodsList" :key="index">
<view class="goods-item-left">
<image :src="item.goods_small_logo||defaultPic" mode="widthFix" class="goods-pic"></image>
</view>
<view class="goods-item-right">
<!-- 商品标题 -->
<view class="goods-name">{{item.goods_name}}</view>
<view class="goods-info-box">
<!-- 商品价格 -->
<view class="goods-price">¥{{item.goods_price}}</view>
</view>
</view>
</view>
</view>
为了防止某些商品的图片不存在,需要在 data 中定义一个默认的图片
javascript
export default {
data() {
return{
defaultPic: 'https://img3.doubanio.com/f/movie/8dd0c794499fe925ae2ae89ee30cd225750457b4/pics/movie/celebrity-default-medium.png'
}
}
}
并在页面渲染时按需使用:
javascript
<image src="{{item.goods_small_logo||defaultPic}}" class="goods-pic"></image>
样式
javascript
.goods-item {
display: flex;
padding-left: 10px 0px;
border-bottom: 1px solid #f0f0f0;
}
.goods-item-left {
margin-right: 5px;
}
.goods-pic {
width: 100px;
height: 100px;
display: block;
}
.goods-item-right {
display: flex;
flex-direction: column;
justify-content: space-around;
}
.goods-name {
font-size: 12px;
}
.goods-price {
font-size: 16px;
color: #cb603b;
}
4、上拉加载更多
onReachBottom
事件处理函数,用来监听页面的上拉触底行为
javascript
onReachBottom() {
//让页码值自增1
this.queryObj.pagenum+=1
//重新获取列表数据
this.getProductList()
},
改造 methods
中的 getProductList
函数,当列表数据请求成功之后,进行新旧数据的拼接处理:
javascript
async getProductList() {
let result = await this.$request({
url: '/goods/search',
data: this.queryObj
})
this.goodsList =[...this.goodsList,...result.message.goods]
this.total = result.message.total
}
通过节流阀防止发起额外的请求
在 data 中定义 isloading
节流阀如下
javascript
data() {
return {
// 是否正在请求数据
isloading: false
}
}
修改 getProductList
方法,在请求数据前后,分别打开和关闭节流阀:
javascript
async getProductList() {
//打开节流阀
this.isloading = true
let result = await this.$request({
url: '/goods/search',
data: this.queryObj
})
//关闭节流阀
this.isloading = false
this.goodsList =[...this.goodsList,...result.message.goods]
this.total = result.message.total
}
在 onReachBottom
触底事件处理函数中,根据节流阀的状态,来决定是否发起请求:
javascript
// 触底的事件
onReachBottom() {
// 判断是否正在请求其它数据,如果是,则不发起额外的请求
if (this.isloading) return
//让页码值自增1
this.queryObj.pagenum+=1
//重新获取列表数据
this.getProductList()
}
判断加载是否完毕
javascript
onReachBottom() {
if(this.queryObj.pagenum*this.queryObj.pagesize>=this.total){
uni.showToast({
title:'加载完毕'
})
}
if(this.isloading) return;
this.queryObj.pagenum+=1
this.getProductList()
},
5、下拉刷新
首先在在page.json配置文件中,开启下来刷新功能
javascript
{
"path" : "pages/products/productList",
"style" :
{
"navigationBarTitleText": "",
"enablePullDownRefresh": true
}
}
下拉刷新
javascript
onPullDownRefresh() {
this.queryObj.pagenum=1
this.getProductList()
uni.stopPullDownRefresh()
}