微信小程序第三天
1. 页面导航
1.1 小程序中实现页面导航的两个方式
-
什么是页面导航
页面导航指的是页面之间的相互跳转,例如,在浏览器中实现页面导航的方式有如下两种:
a标签location.href
-
小程序中实现页面导航的两种方式
-
声明式导航
- 在页面上声明一个
<navigator>导航组件 - 通过点击
<navigator>组件实现页面跳转
- 在页面上声明一个
-
编程式导航
- 调用小程序的导航
API,实现页面的跳转
- 调用小程序的导航
-
1.2 导航到 tabBar 页面
tabBar 页面指的是被配置为 tabBar 的页面
在使用 <navigator> 组件跳转到指定的 tabBar 页面时,需要指定 url 属性和 open-type 属性,其中:
url表示要跳转的页面的地址,必须以/开头open-type表示跳转的方式,必须为switchTab

1.3 导航到非 tabBar 页面
非 tabBar 页面 指的是没有被配置为 tabBar 的页面
在使用 <navigator> 组件跳转到普通的非 tabBar 页面时,则需要指定 url 属性和 open-type 属性,其中:
url表示要跳转的页面的地址,必须以/开头open-type表示跳转的方式,必须为navigate

1.4 后退导航
如果要后退到上一页面或多级页面,则需要指定 open-type 属性和 delta 属性,其中
open-type的值必须是navigateBack,表示要进行后退导航delta的值必须是数字,表示要后退的层级

1.5 导航到 tabBar 页面
调用 wx.switchTab(Object object) 方法,可以跳转到 tabBar 页面,其中 Object 参数对象的属性列表如下:
| 属性 | 类型 | 是否必选 | 说明 |
|---|---|---|---|
| url | string | 是 | 需要跳转的 tabBar 页面的路径 ,路径后不能带参数。 |
| success | function | 否 | 接口调用成功的回调函数 |
| fail | function | 否 | 接口调用失败的回调函数 |
| complete | function | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
示例代码:

1.6 导航到非 tabBar 页面
调用 wx.navigateTo(Object object) 方法,可以跳转到非 tabBar 的页面。其中 Object 参数对象的属性列表如下
| 属性 | 类型 | 必填 | 说明 |
|---|---|---|---|
| url | string | 是 | 需要跳转的应用内非 tabBar 的页面的路径 , 路径后可以带参数 |
| success | function | 否 | 接口调用成功的回调函数 |
| fail | function | 否 | 接口调用失败的回调函数 |
| complete | function | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
示例代码:

1.7 后退导航
调用 wx.navigateBack(Object object) 方法,可以返回上一页面或多级页面。其中 Object 参数对象可选的属性列表如下:
| 属性 | 类型 | 默认值 | 必填 | 说明 |
|---|---|---|---|---|
| delta | number | 1 | 否 | 返回的页面数,如果 delta 大于现有页面数,则返回到首页。 |
| success | function | 否 | 接口调用成功的回调函数 | |
| fail | function | 否 | 接口调用失败的回调函数 | |
| complete | function | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
示例代码:

1.8 声明式导航传参
navigator组件的url属性用来指定将要跳转到的页面的路径。同时,路径的后面还可以携带参数:
参数与路径之间使用?分隔参数键与参数值用=相连不同参数用&分隔
- 不能够往 tabBar 页面传递参数
-
代码示例如下:

1.9 编程式导航传参
-
调用
wx.navigateTo(Object object)方法跳转页面时,也可以携带参数,代码示例如下:- 不能够往 tabBar 页面传递参数
-
示例代码:

1.10 在 onLoad 中接收导航参数
-
通过
声明式导航传参或编程式导航传参所写携带的参数,可以直接在onLoad事件中直接获取到 -
示例代码:

2. 页面事件
2.1 了解什么是下拉刷新
下拉刷新是移动端的专有名词,指的是通过手指在屏幕上的下拉滑动操作,从而重新加载页面数据的行为
2.2 启动下拉刷新
在开启下拉刷新以后,如何不手动停止下拉,下拉动作会一直存在,不会弹回去
在模拟器中会弹回去,在真机上不会弹回去
-
启动下拉刷新的三种方式
-
全局开启下拉刷新
- 在
app.json的window节点中,将enablePullDownRefresh设置为true
- 在
-
局部开启下拉刷新
- 在页面的
.json配置文件中,将enablePullDownRefresh设置为true
- 在页面的
-
使用小程序提供的 API 实现下拉刷新
wx.startPullDownRefresh()
-
-
在实际开发中,推荐使用第 2 种方式,
为需要的页面单独开启下拉刷新的效果
2.3 配置下拉刷新窗口的样式
在全局或页面的 .json 配置文件中,通过 backgroundColor 和 backgroundTextStyle 来配置下拉刷新窗口的样式,其中
backgroundColor用来配置下拉刷新窗口的背景颜色,仅支持 16 进制的颜色值backgroundTextStyle用来配置下拉刷新loading的样式,仅支持dark和light
2.4 监听页面的下拉刷新事件
-
在页面的
.js文件中,通过onPullDownRefresh()函数即可监听当前页面的下拉刷新事件 -
案例1:在页面的
wxml中有如下的UI结构,点击按钮可以让count值自增+1
-
案例2:在触发页面的下拉刷新事件的时候,如果要把
count的值重置为 0,示例代码如下:
2.5 停止下拉刷新的效果
-
当处理完下拉刷新后,下拉刷新的
loading效果会一直显示,不会主动消失, 所以需要手动隐藏loading效果,此时,调用wx.stopPullDownRefresh()可以停止当前页面的上拉刷新 -
示例代码:

2.6 了解什么是上拉触底
上拉触底是移动端的专有名词,通过手指在屏幕上的上拉滑动操作,从而加载更多数据的行为
2.7 监听页面的上拉触底事件
-
在页面的
.js文件中,通过onReachBottom函数即可监听当前页面上的上拉触底事件 -
示例代码如下

2.8 配置上拉触底距离
- 上拉触底距离指的是
触发上拉触底事件时,滚动条距离页面底部的距离 - 可以在全局或页面的
.json配置文件中,通过onReachBottomDistance属性来配置上拉触底的距离 - 小程序默认的触底距离是
50px,在实际开发中,可以根据自己的需求修改这个默认值
3. 生命周期
3.1 什么是生命周期
- 生命周期
(Life Cycle)是指一个对象从 创建 -> 运行 -> 销毁 的整个阶段,强调的是一个时间段 - 小程序的生命周期
- 小程序的
启动,表示生命周期的开始 - 小程序的
关闭,表示生命周期的结束 - 中间小程序运行的过程,就是小程序的生命周期
- 小程序的
3.2 小程序生命周期的两个分类
-
应用生命周期
- 特指小程序从启动 --> 运行 --> 销毁的过程
-
页面生命周期
- 特指小程序中,每个页面的加载 --> 渲染 --> 销毁的过程
-
注意:页面的生命周期范围较小,应用程序的生命周期范围较大

3.3 什么是生命周期函数
-
小程序框架提供的内置函数,会伴随着生命周期,自动按次序执行
-
生命周期函数的作用:
- 允许程序员在特定的生命周期时间点上,执行某些特定的操作
- 例如,页面刚加载的时候,在生命周期函数中自动发起数据请求,获取当前页面的数据
-
注意:生命周期强调的是时间段,生命周期函数强调的是时间点。
3.4 小程序中生命周期函数的两个分类
小程序中的生命周期函数分为两类,分别是:
-
应用生命周期函数
- 特指小程序从启动 --> 运行 --> 销毁期间依次调用的那些函数
-
页面生命周期函数
- 特指小程序中,每个页面从 加载 --> 渲染 --> 销毁期间依次调用的那些函数
3.5 应用的生命周期
-
app.js是小程序执行的入口文件,在app.js中必须调用App()函数,且只能调用一次。其中,App()函数是用来注册并执行小程序的 -
App(Object)函数接收一个Object参数,可以通过这个Object参数,指定小程序的应用生命周期函数 -
app.js中的代码App({ /** * 当小程序初始化完成时,会触发 onLaunch(全局只触发一次) */ onLaunch: function () { }, /** * 当小程序启动,或从后台进入前台显示,会触发 onShow */ onShow: function (options) { }, /** * 当小程序从前台进入后台,会触发 onHide */ onHide: function () { }, /** * 当小程序发生脚本错误,或者 api 调用失败时,会触发 onError 并带上错误信息 */ onError: function (msg) { } })
3.6 页面的生命周期
-
每个小程序页面,必须拥有自己的
.js文件,且必须调用Page()函数,否则报错。其中Page()函数用来注册小程序页面 -
Page(Object)函数接收一个Object参数,可以通过这个Object参数,指定页面的生命周期函数 -
page.js//index.js //获取应用实例 const app = getApp() Page({ /** * 页面的初始数据 */ data: { }, /** * 生命周期函数--监听页面加载 */ onLoad: function (options) { }, /** * 生命周期函数--监听页面初次渲染完成 */ onReady: function () { }, /** * 生命周期函数--监听页面显示 */ onShow: function () { }, /** * 生命周期函数--监听页面隐藏 */ onHide: function () { }, /** * 生命周期函数--监听页面卸载 */ onUnload: function () { }, /** * 页面相关事件处理函数--监听用户下拉动作 */ onPullDownRefresh: function () { }, /** * 页面上拉触底事件的处理函数 */ onReachBottom: function () { }, /** * 用户点击右上角分享 */ onShareAppMessage: function () { } })
4. wxs
4.1 什么是 wxs
-
什么是
wxsWXS (WeiXin Script)是小程序的一套脚本语言,结合WXML,可以构建出页面的结构
-
wxs的应用场景- 小程序中
wxs的典型应用场景就是过滤器
- 小程序中
4.2 wxs 和 JavaScript 的关系
-
虽然
wxs的语法类似于JavaScript,但是wxs和JavaScript是完全不同的两种语言-
wxs有自己的数据类型number数值类型string字符串类型boolean布尔类型object对象类型function函数类型array数组类型date日期类型regexp正则
-
wxs不支持类似于ES6及以上的语法形式- ECMAScript
-
-
JavaScript: DOM、BOM、ECMAScript
-
wxs遵循CommonJS规范module对象:module.exportrequire函数
4.3 拓展: wxs 遵循 CommonJS 模块化规范
CommonJS是javascript的模块化规范之一,小程序的脚本语言wxs遵循了CommonJS规范,因此,使用wxs时的体验和使用node.js的体验比较相似。
-
module对象- 每个
wxs都是独立的模块,每个模块均有一个内置的 module 对象,每个模块都有自己独立的作用域。
- 每个
-
module.exports- 由于
wxs拥有独立作用域,所以在一个模块里面定义的变量与函数,默认为私有的,对其他模块不可见, - 通过
module.exports属性,可以对外共享本模块的私有变量与函数。
- 由于
-
require函数
- 在
wxs模块中引用其他wxs文件模块,可以使用require函数。
- 在
4.4 内嵌 wxs 脚本
-
使用的规则
wxs代码可以编写在wxml文件中的<wxs></wxs>标签内,就像javascript代码可以编写在html文件中的<script></script>标签内一样。wxml文件中的每个<wxs></wxs>标签,必须提供一个module属性,用来指定当前<wxs></wxs>标签的模块名。在单个wxml文件内,建议其值唯一。- module 属性值的命名必须符合下面两个规则:
- 首字符必须是:字母(a-z A-Z),下划线(_)
- 剩余字符可以是:字母(a-z A-Z),下划线(_), 数字(0-9)
-
案例代码

4.5 定义外联的 wxs 脚本
-
使用的规则
wxs代码可以编写在以.wxs为后缀名的文件内,就像javascript代码可以编写在以.js为后缀名文件中一样。
-
实例代码

4.6 使用外联的 wxs 脚本
-
在
wxml中如果要引入外联的wxs脚本,必须为<wxs></wxs>标签添加module和src属性module用来为<wxs></wxs>标签指定模块名,作为当前页面访问这个模块的标识名称src用来指定当前<wxs></wxs>标签要引入的脚本路径,必须是相对路径
-
示例代码

4.7 了解 wxs 的 4 个特点
-
没有兼容性
wxs不依赖于运行时的基础库版本,可以在所有版本的小程序中运行 -
与
javascript不同-
为了降低
wxs的学习成本,wxs语言在设计时大量借鉴了JavaScript语法 -
但本质上,
wxs与javascript是不同的语言,有自己的语法,并不和javascript一致
-
-
隔离性
wxs的运行环境和其他javascript代码是隔离的wxs中不能调用其他javascript文件中定义的函数- 也不能调用小程序提供的
API
-
不能作为事件回调
-
wxs典型的应用场景就是过滤器,经常配置Mustache语法进行使用
-
wxs函数不能作为组件的事件回调
-
-
性能好
iOS设备上比javascript运行快由于运行环境的差异,在
iOS设备上小程序内的wxs会比javascript代码快 2 ~ 20 倍。在
android设备上二者运行效率无差异
5. 案例
5.1 商品列表页面的效果显示

- 页面导航并传参
- 上拉触底时加载下一页数据
- 下拉刷新列表数据
5.2 把项目代码加载到微信开发者工具中
打开微信开发者工具 --> 点击 项目 --> 导入项目 --> 选择项目目录 --> 如有必要,需要替换 AppID
5.3 实现导航跳转并传参
-
创建页面路径
pages/shoplist/shoplist -
将九宫格的容器组件
view改成 导航组件navigator组件,并绑定跳转的Id<view class="grid-list"> <navigator url="/pages/shoplist/shoplist?id={ { item.id }}&title={ { item.name }}" class="grid-item" wx:for="{ { gridList }}" wx:key="id"> <image src="{ { item.icon }}"></image> <text>{ { item.name }}</text> </navigator> </view>
5.4 动态设置商品列表页面的标题内容
-
在
onReady()生命周期函数中对标题栏进行赋值/** * 生命周期函数--监听页面初次渲染完成 */ onReady: function () { wx.setNavigationBarTitle({ title: 'test' }) } -
在
onLoad()生命周期函数中获取到商品列表传递的参数/** * 生命周期函数--监听页面加载 */ onLoad: function (options) { console.log(options) } -
将
options中的数据赋值给data中的数据data: { query: { } }/** * 生命周期函数--监听页面加载 */ onLoad: function (options) { this.setData({ query: options }) } -
在
onReady()生命周期函数中对标题栏进行赋值/** * 生命周期函数--监听页面初次渲染完成 */ onReady: function () { wx.setNavigationBarTitle({ title: this.data.query.title }) }
5.5 创建商铺列表页面的编译模式

5.6 了解 API 接口并定义需要的数据节点
以分页的形式,加载指定分类下商铺列表的数据:
-
接口地址
- https://www.xxxx.cn/categories/:cate_id/shops
URL地址中的:cate_id是动态参数,表示分类的Id
-
请求方式
GET请求
-
请求参数
_page表示请求第几页的数据_limit表示每页请求几条数据
-
响应参数
- 响应的总条数在
header字段中
- 响应的总条数在
-
案例代码
data: {
query: {
},
shoplist: [], // 商铺列表数组
page: 1, // 页码
pagesize: 10, // 每页请求的数量
total: 0 // 总条数
}
5.7 定义 getShopList 方法获取商品列表数据
-
定义获取商品数据的方法,并将数据赋值给
data中的shoplist以及totalgetShopList() { wx.request({ url: `https://www.xxxx.cn/categories/${ this.data.query.id}/shops`, method: 'GET', data: { _page: this.data.page, _limit: this.data.pagesize }, success: (res) => { this.setData({ shoplist: [...this.data.shoplist, ...res.data], total: res.header['X-Total-Count'] - 0 }) } }) } -
在
onLoad钩子函数中,调用getShopList方法/** * 生命周期函数--监听页面加载 */ onLoad: function (options) { this.setData({ query: options }) this.getShopList() }
5.8 渲染商品店铺列表的 ui 结构并美化样式
<!-- 循环遍历生成商铺列表 -->
<view wx:for="{
{shoplist}}" wx:key="id" class="shop-item">
<view class="thumb">
<image src="{
{item.images[0]}}"></image>
</view>
<view class="info">
<text class="shop-title">{
{item.name}}</text>
<!-- 使用wxs 中的方法, 处理手机号码 -->
<text>电话: {
{item.phone}}</text>
<text>地址: {
{item.address}}</text>
<text>营业时间: {
{item.businessHours}}</text>
</view>
</view>
/* 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;
}
5.9 展示 loading 提示效果
-
在网络请求发起之前调用
wx.showLoading方法,显示loading效果wx.showLoading({ title: '数据加载中...', }) -
在网络请求返回以后,隐藏
loading显示complete: () => { wx.hideLoading() } -
完整代码
getShopList() { wx.showLoading({ title: '数据加载中...', }) wx.request({ url: `https://www.xxxx.cn/categories/${ this.data.query.id}/shops`, method: 'GET', data: { _page: this.data.page, _limit: this.data.pagesize }, success: (res) => { this.setData({ shoplist: [...this.data.shoplist, ...res.data], total: res.header['X-Total-Count'] - 0 }) }, complete: () => { wx.hideLoading() } }) }
5.10 上拉触底时请求下一页数据
-
配置页面触底的距离
{ "usingComponents": { }, "onReachBottomDistance": 100 } -
在
onReachBottom事件处理程序中处理逻辑/** * 页面上拉触底事件的处理函数 */ onReachBottom: function () { this.setData({ page: this.data.page + 1 }) this.getShopList() }
5.11 对上拉触底事件进行节流控制
-
对上拉触底进行节流处理
-
在
data中定义isLoading节流阀false表示当前没有进行任何数据请求true表示当前正在进行数据请求
-
在
getShopList方法中修改isLoading节流阀的值- 在刚调用
getColors时将节流阀设置为true - 在网络请求的
complete回调函数中,将节流阀重置为false
- 在刚调用
-
在
onReachBottom中判断节流阀的值,从而对数据请求进行节流控制- 如果节流阀的值为
true,则阻止当前请求 - 如果节流阀的职位
false,则发起数据请求
- 如果节流阀的值为
-
-
代码实现
/** * 页面的初始数据 */ data: { isLoading: false // 控制是否显示 loading }getShopList() { this.setData({ isLoading: true }) // coding…… wx.request({ url: `https://www.xxxx.cn/categories/${ this.data.query.id}/shops`, // coding…… complete: () => { wx.hideLoading() this.setData({ isLoading: false }) } }) }/** * 页面上拉触底事件的处理函数 */ onReachBottom: function () { if (this.data.isLoading) return this.setData({ page: this.data.page + 1 }) this.getShopList() }
5.12 演示并分析数据加载问题
- 当没有数据时,依然能发起数据请求,这样就造成了带宽的浪费
- 在实际开发中,如果没有数据,不应该发起额外的数据请求
5.13 介绍判断是否还有下一页数据的公式
-
如果下面的公式成立,则证明没有下一页数据了:
-
页码值 * 每页显示多少条数据 >= 总数据条数
page*pageSize>=total
- 举例1:假设总共有 77 条数据,如果每页显示 10 条数据,则总共分为 8 页,其中第 8 页只有 7 条数据 - page (7)* pageSize (10) >= total(77)不成立, 所以有下一页数据 - page (8)* pageSize (10) >= total(77)成立, 所以没有下一页数据- 举例2:假设总共有 80 条数据,如果每页显示 10 条数据,则总共分为 8 页,其中第 8 页面有 10条数据 - page (7)* pageSize (10) >= total(80)不成立, 所以有下一页数据 - page (8)* pageSize (10) >= total(80)成立, 所以没有下一页数据
-
-
方式二:
- 可以将
total的值, 和数组的长度进行对比
- 可以将
5.14 根据公式判断是否还有下一页的数据
-
在
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() }
5.15 为商铺列表页面开启下拉刷新效果
-
开启下拉刷新效果
{ "usingComponents": { }, "onReachBottomDistance": 100, "enablePullDownRefresh": true, "backgroundColor": "#efefef", "backgroundTextStyle": "dark" }
5.16 实现下拉刷新的逻辑
-
在
onPullDownRefresh逻辑函数中监听用户下拉动作- 重置关键的数据
- 重新发起数据的请求
/** * 页面相关事件处理函数--监听用户下拉动作 */ onPullDownRefresh: function () { // 需要重置关键的数据 this.setData({ page: 1, shoplist: [], total: 0 }) // 重新发起数据请求 this.getShopList() }
5.17 解决下拉窗口效果不会自动关闭的问题
- 在
complete回调函数中,调用关闭下拉刷线窗口的API - 但是我们执行上拉加载更多的时候,是不需要执行这个方法的
- 所以我们在执行下拉,对数据重置,重新获取数据的方法中,传入回调函数
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
// 需要重置关键的数据
this.setData({
page: 1,
shoplist: [],
total: 0
})
// 重新发起数据请求
this.getShopList(() => {
wx.stopPullDownRefresh()
})
}
complete: () => {
wx.hideLoading()
this.setData({
isLoading: false
})
cb && cb()
}
5.18 使用 wxs 处理手机号
-
在
utils目录下创建tools.wxs文件,并创建splitPhone方法- splice()
- 第一个参数:添加/删除项目的位置
- 第二个参数:需要删除的数量
- 第三个参数:可选,向数组中添加的新项
function splitPhone(str) { if (str.length !== 11) return str var arr = str.split('') arr.splice(3, 0, '-') arr.splice(8, 0, '-') return arr.join('') } module.exports = { splitPhone: splitPhone } - splice()
-
在
shoplist.wxml文件中导入tools.wxs文件
<wxs src="../../utils/tools.wxs" module="tools"></wxs>
-
使用封装的
splitPhone方法<text>电话: { {tools.splitPhone(item.phone)}}</text>
5.19 在手机上预览不了的问题
-
问题
-
小程序如果需要发起网络请求,必须在 服务器域名中对域名进行配置,
-
小程序会往配置域名中发起请求,
-
但是,我们并没有在后台配置服务器域名,所以在手机上访问不了
-
-
解决方案
- 手机扫码 --> 点击小程序右上角 三个点 --> 弹出面板,点击开发调试 --> 弹出新的面板,点击打开调试
- 点击悬浮框
vConsole,会显示页面的结构,以及 log 等,在实际开发中,可以配置模拟器进行测试
如有不足,请多指教,
未完待续,持续更新!
大家一起进步!
转载:https://blog.csdn.net/qq_40440961/article/details/115855086