一、页面导航
1.简介
1.1 什么是页面导航?
1.2 小程序中实现页面导航的两种方式
2.声明式导航
2.1 导航到 tabBar 页面
<navigator url="/pages/message/message" open-type="switchTab">导航到消息页面</navigator>
2.2 导航到非 tabBar 页面
<navigator url="/pages/info/info" open-type="navigate">导航到info页面</navigator>
或者:<navigator url="/pages/info/info">导航到info页面</navigator>
2.3 后退导航
<navigator open-type="navigateBack" delta='1' >后退</navigator>
或者:<navigator open-type="navigateBack">后退</navigator>
3.编程式导航
3.1 导航到 tabBar 页面
3.2 导航到非 tabBar 页面
3.3 后退导航
4.导航传参
4.1 声明式导航传参
跳转到非tabBar页面
和a标签传参数值是一样的!
4.2 编程式导航传参
跳转到非tabBar页面
和a标签传参数值是一样的!
4.3 在 onLoad函数 中接收导航参数
二、页面事件
1.下拉刷新事件
1.1 什么是下拉刷新
下拉刷新是移动端的专有名词,指的是通过手指在屏幕上的下拉滑动操作,从而重新加载页面数据的行为。
1.2 启用下拉刷新
1.3 配置下拉刷新窗口的样式
1.4 监听页面的下拉刷新事件
都是写在Page对象里面的
1.5 停止下拉刷新的效果
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
// console.log('触发了message页面的下拉刷新')
this.setData({
count: 0
})
wx.stopPullDownRefresh()
},
2.上拉触底事件
2.1 什么是上拉触底
上拉触底是移动端的专有名词,通过手指在屏幕上的上拉滑动操作,从而加载更多数据的行为。
2.2 监听页面的上拉触底事件
2.3 配置上拉触底距离
3.上拉触底案例
3.1 案例效果展示
3.2 案例的实现步骤
3.3 具体实现
步骤1 - 定义获取随机颜色的方法
步骤2 - 在页面加载时获取初始数据
步骤3 - 渲染 UI 结构并美化页面效果
步骤4 - 上拉触底时获取随机颜色
步骤5 - 添加 loading 提示效果:showLoading函数
步骤6 - 对上拉触底进行节流处理
原因:有可能我们在很短时间内触发很多次触底事件,那这样会不断地请求,并且只会返回最后一次的数据
解决:我们应当进行节流处理,也就是正在进行网络请求时拒绝再次请求
// pages/contact/contact.js
Page({
/**
* 页面的初始数据
*/
data: {
colorList: [],
isloding: false //节流标志变量
},
getColors() {
this.setData({
isloding: true //正在发起网络请求
})
// 需要展示 loading 效果
wx.showLoading({
title: '数据加载中...'
})
wx.request({
url: 'https://www.escook.cn/api/color',
method: 'get',
success: ({ data: res }) => {
this.setData({
colorList: [...this.data.colorList, ...res.data]
})
},
complete: () => {
wx.hideLoading()
this.setData({
isloding: false
})
}
})
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
this.getColors()
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
if (this.data.isloding) return //如果正在进行网络请求,就直接结束
this.getColors()
}
})
4.扩展
自定义编译模式:
解释:就是每次编译(重新编译)之后进入的页面,方便我们针对某一个页面进行开发
默认情况下,每次编译都会进入首页
三、生命周期
1.什么是生命周期
2.生命周期的分类
3.什么是生命周期函数
4.生命周期函数的分类
5.应用的生命周期函数
输入App,然后点击那个函数,会自动出现以下内容的生命周期函数:
小程序进入后台:意思就是小程序被放到手机的后台运行了,也就是把页面切走了!
//app.js
App({
/**
* 当小程序初始化完成时,会触发 onLaunch(全局只触发一次)
*/
onLaunch: function () {
// console.log('onLaunch')
},
/**
* 当小程序启动,或从后台进入前台显示,会触发 onShow
*/
onShow: function (options) {
// console.log('onShow')
},
/**
* 当小程序从前台进入后台,会触发 onHide
*/
onHide: function () {
// console.log('onHide')
},
/**
* 当小程序发生脚本错误,或者 api 调用失败时,会触发 onError 并带上错误信息
*/
onError: function (msg) {
// console.log('onError')
}
})
模拟切后台:再次点击就会切到前台
6.页面的生命周期函数
输入Page,然后点击那个函数,会自动出现以下内容的生命周期函数:
// pages/home/home.js
Page({
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
}
})
用的多的:
onLoad:初始化页面的数据、转存页面接收到的参数options
onReady:修改页面里面的内容,有一些相关的方法,比如修改页面标题
四、WXS 脚本
1.概述
1.1 什么是 wxs
WXS(WeiXin Script)是小程序独有的一套脚本语言,WXS 结合 WXML,可以构建出页面的结构。
1.2 wxs 的应用场景
wxml 中无法调用在页面的 .js 中定义的函数(只是能用事件绑定而已),但是 wxml 中可以调用 wxs 中定义的函数。
因此,小程序中 wxs 的典型应用场景就是“过滤器”。
(vue3已经删除过滤器)
1.3 wxs 和 JavaScript 的关系
2.基础语法
2.1 内嵌 wxs 脚本
2.2 定义外联的 wxs 脚本
/utils/tools.wxs
function toLower(str) {
return str.toLowerCase()
}
module.exports = {
toLower: toLower
}
2.3 使用外联的 wxs 脚本
<wxs src="../../utils/tools.wxs" module="tools"></wxs>
3.WXS 的特点
3.1 与 JavaScript 不同
为了降低 wxs(WeiXin Script)的学习成本, wxs 语言在设计时借大量鉴了 JavaScript 的语法。
但是本质上,wxs 和 JavaScript 是完全不同的两种语言!
3.2 不能作为组件的事件回调
里面不可以调用js文件的函数,但是可以调用wxs文件的函数
但是wxs文件的函数不能作为事件函数
utils文件夹里面的wxs文件是给wxml调用的,js文件是给js调用的!
js与wxs彼此都不能进行调用
3.3 隔离性
3.4 性能好
五、案例 - 本地生活(列表页面)
1. 演示页面效果以及主要功能
2.列表页面的 API 接口
3.判断是否还有下一页数据
4.具体实现
home.xwml
<!--pages/home/home.wxml-->
<!-- 轮播图区域 -->
<swiper indicator-dots circular>
<swiper-item wx:for="{{swiperList}}" wx:key="id">
<image src="{{item.image}}"></image>
</swiper-item>
</swiper>
<!-- 九宫格区域 -->
<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>
<!-- 图片区域 -->
<view class="img-box">
<image src="/images/link-01.png" mode="widthFix"></image>
<image src="/images/link-02.png" mode="widthFix"></image>
</view>
home.js
// pages/home/home.js
Page({
/**
* 页面的初始数据
*/
data: {
// 存放轮播图数据的列表
swiperList: [],
// 存放九宫格数据的列表
gridList: []
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
this.getSwiperList()
this.getGridList()
},
// 获取轮播图数据的方法
getSwiperList() {
wx.request({
url: 'https://www.escook.cn/slides',
method: 'GET',
success: (res) => {
this.setData({
swiperList: res.data
})
}
})
},
// 获取九宫格数据的方法
getGridList() {
wx.request({
url: 'https://www.escook.cn/categories',
method: 'GET',
success: (res) => {
this.setData({
gridList: res.data
})
}
})
}
})
shoplist.wxml
<!--pages/shoplist/shoplist.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>电话:{{tools.splitPhone(item.phone)}}</text>
<text>地址:{{item.address}}</text>
<text>营业时间:{{item.businessHours}}</text>
</view>
</view>
<wxs src="../../utils/tools.wxs" module="tools"></wxs>
shoplist.js
// pages/shoplist/shoplist.js
Page({
/**
* 页面的初始数据
*/
data: {
query: {}, //传入的参数:要查询的条件(要显示什么板块的内容)
shopList: [],
page: 1,
pageSize: 10,
total: 0,
isloading: false
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
this.setData({
query: options //存储传入的参数
})
this.getShopList()
},
// 以分页的形式获取商铺列表数据的方法
getShopList(cb) {
this.setData({
isloading: true
})
// 展示 loading 效果
wx.showLoading({
title: '数据加载中...'
})
wx.request({
//取值:直接this.data.属性即可,因为this代表Page对象
url: `https://www.escook.cn/categories/${this.data.query.id}/shops`,
method: 'GET',
data: { //发送到服务器的数据
_page: this.data.page, //第几页
_limit: this.data.pageSize //显示的条数:即pageSize
},
success: (res) => {
this.setData({
shopList: [...this.data.shopList, ...res.data], //拼接数据
total: res.header['X-Total-Count'] - 0 //返回的数据里面有一个header对象,里面的X-Total-Count属性就是数据的实际总数,-0是为了把字符串转换为数字
})
},
complete: () => {
wx.hideLoading() // 隐藏 loading 效果
this.setData({ isloading: false })
// wx.stopPullDownRefresh() //注:不应当直接写在这里,而是应该在需要的时候传进来,因为不是所有的获取数据的时候都需要停止下拉刷新
// 下面就是调用这个函数:wx.stopPullDownRefresh(),停止下拉刷新的效果
cb && cb() //短路运算:有没有传入cb,如果传了就进行调用
}
})
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
wx.setNavigationBarTitle({
title: this.data.query.title //动态显示标题
})
},
/**
* 页面相关事件处理函数--监听用户下拉刷新动作
*/
onPullDownRefresh: function () {
// 需要重置数据
this.setData({
page: 1,
shopList: [],
total: 0
//pageSize不用重置,因为是固定的
})
// 重新发起数据请求
this.getShopList(() => {
wx.stopPullDownRefresh() //传入回调函数作为参数:停止下拉刷新的效果
})
},
/**
* 页面上拉触底事件处理函数--监听用户上拉触底动作
*/
onReachBottom: function () {
//当没有数据时就不应该发起额外的请求!
if (this.data.page * this.data.pageSize >= this.data.total) { // 证明没有下一页的数据了
return wx.showToast({ //显示消息提示框的api
title: '数据加载完毕!', //必须配置
icon: 'none' //默认是success图标,如果不希望展示就写为none
})
}
// 判断是否正在加载其他数据
if (this.data.isloading) return
// 如果可以进行加载,那么页码值 +1
this.setData({
page: this.data.page + 1
})
// 获取下一页数据
this.getShopList()
}
})
shoplist.wxss
/* pages/shoplist/shoplist.wxss */
.shop-item {
display: flex;
padding: 15rpx;
border: 1rpx solid #efefef;
border-radius: 8rpx;
margin: 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;
}
tools.wxs
过滤器处理手机号:改为xxx-xxxx-xxxx的格式
function splitPhone(str) {
if(str.length !== 11) return str
var arr = str.split('') //按空字符分隔,即把手机号分成11个元素,放入一个数组
arr.splice(3, 0, '-') //在索引为3的位置,不删除元素(删除0个),插入一个-
arr.splice(8, 0, '-')
return arr.join('') //将数组元素合并,变成一个字符串
}
module.exports = {
splitPhone: splitPhone
}
总结: