| 知识点名称 | 知识点内容 | 难度系数 | 要求程度 |
|---|---|---|---|
| 页面导航 | 声明式导航、编程式导航、导航传参 | 3星 | 掌握 |
| 页面事件 | 下拉刷新、上拉触底、上拉触底案例、自定义编译模式 | 3星 | 掌握 |
| 生命周期 | 生命周期分类、应用生命周期、页面生命周期 | 3星 | 掌握 |
| wxs学习 | 认识wxs及应用场景、掌握基础语法、掌握使用方式、注意要点 | 4星 | 了解 |
| 本地生活案例(列表) | 导航跳转列表并传参、获取数据,渲染数据、滚动分页、下拉刷新、wxs处理手机号 | 4星 | 掌握 |
文章目录
- 1、学习目标
- 2、页面导航
- 2.1、认识导航
- 什么是页面导航
- 实现导航的两种方式
- 声明式导航
- 编程式导航
- 2.2、声明式导航
- 导航到 tabBar 页面
- 导航到非 tabBar 页面
- 后退导航
- 2.3、编程式导航
- 导航到 tabBar
- 导航到非 tabBar 页面
- 编程式导航 – 后退导航
- 2.4、导航传参
- 声明式传递参数
- 编程式传递参数
- 接收参数
- 3、页面事件
- 3.1、下拉刷新
- 启动下拉刷新
- 配置下拉刷新窗口的样式
- 监听页面的下拉刷新事件
- 停止下拉刷新的效果
- 3.2、上拉触底
- 监听页面的上拉触底事件
- 配置上拉触底距离
- 3.3、上拉触底案例
- 效果展示
- 思路分析
- 拓展-自定义编译模式
- 4、生命周期
- 4.1、生命周期定义
- 小程序生命周期定义
- 小程序生命周期分类
- 4.2、生命周期函数
- 两个分类说明
- 应用的生命周期
- 页面的生命周期
- 5、wxs学习
- 5.1 什么是 `wxs`
- 5.2 wxs 和 JavaScript 的关系
- 5.3 拓展: `wxs` 遵循 `CommonJS` 模块化规范
- 5.4 内嵌 wxs 脚本
- 5.5 定义外联的 wxs 脚本
- 5.6 使用外联的 wxs 脚本
- 问题
- 5.7 了解 wxs 的 4 个特点
- 问题
- 6. 案例
- 6.1 商品列表页面的效果显示
- 6.2 把项目代码加载到微信开发者工具中
- 6.3 实现导航跳转并传参
- 6.4 动态设置商品列表页面的标题内容
- 6.5 创建商铺列表页面的编译模式
- 6.6 了解 API 接口并定义需要的数据节点
- 6.7 定义 getShopList 方法获取商品列表数据
- 6.8 渲染商品店铺列表的 ui 结构并美化样式
- 6.9 展示 loading 提示效果
- 6.10 上拉触底时请求下一页数据
- 6.11 对上拉触底事件进行节流控制
- 6.12 演示并分析数据加载问题
- 6.13 介绍判断是否还有下一页数据的公式
- 6.14 根据公式判断是否还有下一页的数据
- 6.15 为商铺列表页面开启下拉刷新效果
- 6.16 实现下拉刷新的逻辑
- 6.17 解决下拉窗口效果不会自动关闭的问题
- 6.18 使用 wxs 处理手机号
思考
❓ Vue 中实现导航跳转的方式有几种,分别是什么?
Vue.use(VueRouter)做了什么事情
Vue 中实现导航跳转的方式有 2 种
- 声明式导航
- 编程式导航
router.push('/地址')
页面导航指的是页面之间的相互跳转,例如,在浏览器中实现页面导航的方式有如下两种:
a 标签
location.href
在页面上声明一个 导航组件通过点击 组件实现页面跳转,具体参见文档 【组件=>导航=>navigator】
调用小程序的导航 API,实现页面的跳转,具体参见文档 【api=>路由】
tabBar页面/非tabBar页面
tabBar 页面指的是被配置为 tabBar 的页面 在使用 组件跳转到指定的 tabBar 页面时,需要指定 url 属性和 open-type属性,例如:
跳转到tabBar页面
url 表示要跳转的 页面的地址,必须以 /开头open-type 表示 跳转的方式 ,必须为 switchTab非 tabBar 页面 指的是没有被配置为 tabBar 的页面 在使用 组件跳转到普通的非tabBar 页面时,需要指定 url 属性和 open-type属性,例如:
跳转到 非tabBar页面
url 表示要跳转的 页面的地址,必须以 /开头open-type 表示 跳转的方式 ,必须为 navigate如果要后退到上一页面或多级页面,则需要指定 open-type 属性和 delta 属性,例如:
后退导航
open-type 的值必须是 navigateBack,表示要进行后退导航delta 的值必须是数字,表示要后退的层级urltabBar页面是无效的调用wx.switchTab({...})方法,可以跳转到 tabBar 页面,其中 Object 参数对象的属性列表如下:
| 属性 | 类型 | 是否必选 | 说明 |
|---|---|---|---|
| url | string | 是 | 需要跳转的 tabBar 页面的路径 ,路径后不能带参数。 |
| success | function | 否 | tab跳转成功的回调函数 |
| fail | function | 否 | tab跳转失败的回调函数 |
| complete | function | 否 | tab跳转结束的回调函数(调用成功、失败都会执行) |
编程式导航到 tabBar 页面示例如下:
// 页面js文件中
tabFn(){wx.switchTab({url: "/pages/home/home"})
}
调用wx.navigateTo({...})方法,可以跳转到非 tabBar 的页面。其中 Object 参数对象的属性列表如下
| 属性 | 类型 | 必填 | 说明 |
|---|---|---|---|
| url | string | 是 | 需要跳转的应用内非tabBar 的页面的路径, 路径后可以带参数 |
| success | function | 否 | 接口调用成功的回调函数 |
| fail | function | 否 | 接口调用失败的回调函数 |
| complete | function | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
编程式导航到非 tabBar 页面示例如下:
// 页面js文件中
tabFun(){wx.navigateTo({url:"/pages/event/event"})
}
调用wx.navigateBack({ ... }) 方法,可以返回上一页面或多级页面。其中 Object 参数对象可选的属性列 表如下:
| 属性 | 类型 | 默认值 | 必填 | 说明 |
|---|---|---|---|---|
| delta | number | 1 | 否 | 返回的页面数,如果delta 大于现有页面数,则返回到首页。 |
| success | function | 否 | 接口调用成功的回调函数 | |
| fail | function | 否 | 接口调用失败的回调函数 | |
| complete | function | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
编程式导航实现后退导航示例如下:
// 页面js文件中
backFn(){wx.navigateBack({delta: 1})
}
总结:
编程式导航跳转
- tabBar界面
wx.switchTab({ url: '' })- 非tabBar界面
wx.navigateTo({ url: '' })- 后退导航
wx.navigateBack({ delta: 1 })
navigator 组件的url 属性用来指定将要跳转到的页面的路径。同时,路径的后面还可以携带参数,示例如下:
跳转到非 tabBar页面
?分隔= 相连& 分隔tabBar页面传递参数调用 wx.navigateTo({ ... })方法跳转页面时,也可以携带参数,代码示例如下:
// 页面js文件中
tabFun(){wx.navigateTo({url:"/pages/event/event?id=10&tom=1"})
}
tabBar页面传递参数【总结】小程序里面页面传参依靠的是URL上面的查询参数,但是不能给tabBar页面传递
通过 声明式导航传参 或 编程式导航传参 所写携带的参数,可以直接在 onLoad 事件中直接获取到,示例代码如下
// 页面的js文件中/*** 生命周期函数--监听页面加载*/onLoad: function (options) {console.log(options) // options 就是页面传递过来的参数}
总结概况
❓ 小程序中实现导航跳转的方式有几种,分别是什么?
- 小程序 中实现导航跳转的方式有 2 种
- 声明式导航(
)和编程式导航 (小程序 API)
总结概况
❓ 小程序中如何实现导航传参以及如何获取参数?
- url 路径的后面携带参数,形如:
key=value&key2=value2- onLoad 事件中使用形参 options 直接获取到
思考
❓ 什么是下拉刷新
下拉刷新 是移动端的专有名词,指的是通过手指在屏幕上的下拉滑动操作,从而 重新加载页面数据 的行为
启动下拉刷新的三种方式,分别是:
全局开启下拉刷新
在app.json的 window节点中,将 enablePullDownRefresh设置为 true
局部开启下拉刷新
在页面的.json 配置文件中,将 enablePullDownRefresh设置为true
使用小程序提供的 API 实现下拉刷新
wx.startPullDownRefresh() // 主动触发下拉刷新,就像手指下拉一样的效果
注意: pc模拟器里面是无效的,手机真机是可以实现该效果
在全局或页面的.json 配置文件中,通过backgroundColor和backgroundTextStyle 来配置下拉刷新窗口的样 式,其中
backgroundColor 用来配置 下拉刷新 窗口的背景颜色,仅支持 16 进制的颜色值backgroundTextStyle 用来配置 下拉刷新loading的样式,仅支持 dark和light{"usingComponents": {},"enablePullDownRefresh": true, // 页面开启下拉刷新"backgroundColor":"#ff0000", // 背景色"backgroundTextStyle":'light' // loading 样式
}
在页面的 .js文件中,通过 onPullDownRefresh()函数即可监听当前页面的下拉刷新事件
Page({/*** 页面的初始数据*/data: {count:1},/*** 页面相关事件处理函数--监听用户下拉动作*/onPullDownRefresh: function () {// 用户下拉后,将count的值设置为0this.setData({count:0})},
})
当处理完下拉刷新后,下拉刷新的loading 效果会一直显示,不会主动消失, 所以需要手动隐藏loading效果, 此时,调用 wx.stopPullDownRefresh()可以停止当前页面的上拉刷新
/*** 页面相关事件处理函数--监听用户下拉动作*/onPullDownRefresh: function () {// 用户下拉后,将count的值设置为0this.setData({count:0})// 关闭下拉刷新wx.stopPullDownRefresh()}
思考
❓ 什么是上拉触底
上拉触底是移动端的专有名词,通过手指在屏幕上的上拉滑动操作,从而加载更多数据的行为
在页面的.js 文件中,通过onReachBottom 函数即可监听当前页面上的上拉触底事件
/*** 页面上拉触底事件的处理函数*/onReachBottom: function () {console.log('上拉触底喽')},
.json 配置文件中,通过onReachBottomDistance属性来配置上拉触底的距离50px,在实际开发中,可以根据自己的需求修改这个默认值{"usingComponents": {},"enablePullDownRefresh": true,"backgroundColor":"#ff0000","onReachBottomDistance":100 // 距离底部还有100就触发
}
总结概况
❓ 小程序中如何监听下拉刷新以及上拉触底加载
在页面的
.js文件中使用onPullDownRefresh()函数 和onReachBottom()函数

请求数据的过程当中需要展示loading效果,数据获取到以后,loading消失
wxml结构,渲染数据,美化UI样式结构实现步骤
获取自定义颜色的方法
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})}})},
定义模板内容
{ colorList }}" style="background-color: rgb({{ item }});"> {{ item }}
样式
/* pages/color/color.wxss */.item {/* width: 100%; */height: 350rpx;color: white;line-height: 350rpx;text-align: center;border-radius: 20rpx;margin: 20rpx;
}



思考
❓ 现实生活中什么是生命周期?
生命周期 (Life Cycle) 是指一个对象从 创建 -> 运行 -> 销毁 的整个阶段,强调的是一个时间段,例如:
- 张三出生,表示这个人的生命周期开始
- 张三离世,表示这个人的生命周期结束
- 张三一生,就是张三的生命周期
- 小程序的 启动,表示 生命周期的开始
- 小程序的 关闭,表示 生命周期的结束
- 中间小程序运行的过程,就是小程序的生命周期

小程序中的生命周期函数分为两类,分别是:
应用的生命周期app.js 是小程序执行的入口文件,在 app.js 中必须调用 App() 函数,且只能调用一次。其中,App() 函数是用 来注册并执行小程序的App(Object) 函数接收一个 Object 参数,可以通过这个Object 参数,指定小程序的应用生命周期函数
App({/*** 当小程序初始化完成时,会触发 onLaunch(全局只触发一次)*/onLaunch: function () {},/*** 当小程序启动,或从后台进入前台显示,会触发 onShow*/onShow: function (options) { },/*** 当小程序从前台进入后台,会触发 onHide*/onHide: function () {},/*** 当小程序发生脚本错误,或者 api 调用失败时,会触发 onError 并带上错误信息*/onError: function (msg) {}
})
// pages/list/list.js
Page({.../*** 生命周期函数--监听页面加载*/onLoad: function (options) {console.log('onLoad');},/*** 生命周期函数--监听页面初次渲染完成*/onReady: function () {console.log('onReady');},/*** 生命周期函数--监听页面显示*/onShow: function () {console.log('onShow');},/*** 生命周期函数--监听页面隐藏*/onHide: function () {console.log('onHide');},/*** 生命周期函数--监听页面卸载*/onUnload: function () {console.log('onUnload');},...
})
总结概况
❓ 小程序生命周期包含几类,分别是什么 ?
- 小程序中的生命周期,分为 2 类
- 分别是 应用生命周期 和 页面生命周期,其中应用生命周期包裹这页面生命周期
wxswxs WXS (WeiXin Script) 是小程序的一套脚本语言,结合 WXML,可以构建出页面的结构wxs的应用场景 wxml 中无法调用在页面的 .js 中定义的函数,但是 ,wxml 中可以调用 wxs 中定义的函数,因此,小程序中 wxs 的 典型应用场景 就是 过滤器wxs的语法类似于JavaScript,但是wxs和JavaScript 是完全不同的两种语言 wxs有自己的数据类型 number 数值类型string 字符串类型boolean 布尔类型object 对象类型function 函数类型array 数组类型date 日期类型regexp 正则wxs 不支持类似于 ES6 及以上的语法形式wxs遵循CommonJS规范 module 对象:module.exportrequire 函数wxs 遵循 CommonJS 模块化规范
CommonJS是javascript的模块化规范之一,小程序的脚本语言wxs遵循了CommonJS规范,因此,使用wxs时的体验和使用node.js的体验比较相似。
module对象 wxs 都是独立的模块,每个模块均有一个内置的 module 对象,每个模块都有自己独立的作用域。module.exports wxs 拥有独立作用域,所以在一个模块里面定义的变量与函数,默认为私有的,对其他模块不可见,module.exports 属性,可以对外共享本模块的私有变量与函数。wxs 模块中引用其他 wxs 文件模块,可以使用 require 函数。使用的规则
wxs 代码可以编写在 wxml 文件中的 标签内,就像 javascript 代码可以编写在 html 文件中的 标签内一样。wxml 文件中的每个 标签,必须提供一个 module 属性,用来指定当前 标签的模块名。在单个 wxml 文件内,建议其值唯一。案例代码

wxs 代码可以编写在以 .wxs 为后缀名的文件内,就像 javascript 代码可以编写在以 .js 为后缀名文件中一样。wxml中如果要引入外联的wxs脚本,必须为标签添加module和src属性 modu le 用来为 标签指定模块名,作为当前页面访问这个模块的标识名称src 用来指定当前 标签要引入的脚本路径,必须是相对路径!!!
没有兼容性
wxs 不依赖于运行时的基础库版本,可以在所有版本的小程序中运行
与 javascript 不同
wxs 的学习成本, wxs 语言在设计时大量借鉴了 JavaScript 语法wxs 与 javascript 是不同的语言,有自己的语法,并不和 javascript 一致隔离性
wxs的运行环境和其他javascript代码是隔离的 wxs 中不能调用其他 javascript 文件中定义的函数API不能作为事件回调
wxs 典型的应用场景就是 过滤器,经常配置 Mustache 语法进行使用
wxs 函数不能作为组件的事件回调

性能好
iOS设备上比 javascript 运行快
由于运行环境的差异,在 iOS 设备上小程序内的 wxs 会比 javascript 代码快 2 ~ 20 倍。
在 android 设备上二者运行效率无差异

打开微信开发者工具 --> 点击 项目 --> 导入项目 --> 选择项目目录 --> 如有必要,需要替换 AppID
创建页面路径
pages/shoplist/shoplist
将九宫格的容器组件 view 改成 导航组件 navigator 组件,并绑定跳转的 Id
{ item.id }}&title={{ item.name }}" class="grid-item" wx:for="{{ gridList }}" wx:key="id">{ item.icon }}"> {{ item.name }}
在 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})
}

以分页的形式,加载指定分类下商铺列表的数据:
接口地址
URL 地址中的 :cate_id 是动态参数,表示分类的 Id请求方式
GET 请求请求参数
_page 表示请求第几页的数据_limit 表示每页请求几条数据案例代码
data: {query: {},shoplist: [], // 商铺列表数组page: 1, // 页码pagesize: 10, // 每页请求的数量total: 0 // 总条数
}
定义获取商品数据的方法,并将数据赋值给 data 中的 shoplist 以及 total
getShopList() {wx.request({url: `https://www.escook.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()
}
{shoplist}}" wx:key="id" class="shop-item">{item.images[0]}}"> {{item.name}} 电话: {{item.phone}} 地址: {{item.address}} 营业时间: {{item.businessHours}}
/* 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;
}
在网络请求发起之前调用 wx.showLoading 方法,显示 loading 效果
wx.showLoading({title: '数据加载中...',
})
在网络请求返回以后,隐藏 loading 显示
complete: () => {wx.hideLoading()
}
完整代码
getShopList() {wx.showLoading({title: '数据加载中...',})wx.request({url: `https://www.escook.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()}})
}
配置页面触底的距离
{"usingComponents": {},"onReachBottomDistance": 100
}
在 onReachBottom 事件处理程序中处理逻辑
/*** 页面上拉触底事件的处理函数*/
onReachBottom: function () {this.setData({page: this.data.page + 1})this.getShopList()
}
对上拉触底进行节流处理
在 data 中定义 isLoading 节流阀
false 表示当前没有进行任何数据请求true 表示当前正在进行数据请求在 getShopList 方法中修改 isLoading 节流阀的值
getColors 时将节流阀设置为 truecomplete 回调函数中,将节流阀重置为 false在 onReachBottom 中判断节流阀的值,从而对数据请求进行节流控制
true,则阻止当前请求false,则发起数据请求代码实现
/*** 页面的初始数据*/
data: {isLoading: false // 控制是否显示 loading
}
getShopList() {this.setData({isLoading: true})// coding……wx.request({url: `https://www.escook.cn/categories/${this.data.query.id}/shops`,// coding……complete: () => {wx.hideLoading()this.setData({isLoading: false})}})
}
/*** 页面上拉触底事件的处理函数*/
onReachBottom: function () {if (this.data.isLoading) returnthis.setData({page: this.data.page + 1})this.getShopList()
}
如果下面的公式成立,则证明没有下一页数据了:
页码值 * 每页显示多少条数据 >= 总数据条数
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 的值, 和数组的长度进行对比在 onReachBottom 钩子函数中判断数据是否加载完毕
onReachBottom: function () {if (this.data.page * this.data.pagesize >= this.data.total) {// 没有更多用户时候的提示return wx.showToast({title: '数据加载完毕!',icon: 'none'})}if (this.data.isLoading) returnthis.setData({page: this.data.page + 1})this.getShopList()
}
开启下拉刷新效果
{"usingComponents": {},"onReachBottomDistance": 100,"enablePullDownRefresh": true,"backgroundColor": "#efefef","backgroundTextStyle": "dark"
}
在 onPullDownRefresh 逻辑函数中监听用户下拉动作
/*** 页面相关事件处理函数--监听用户下拉动作*/
onPullDownRefresh: function () {// 需要重置关键的数据this.setData({page: 1,shoplist: [],total: 0})// 重新发起数据请求this.getShopList()
}
complete 回调函数中,调用关闭下拉刷线窗口的 API/*** 页面相关事件处理函数--监听用户下拉动作*/
onPullDownRefresh: function () {// 需要重置关键的数据this.setData({page: 1,shoplist: [],total: 0})// 重新发起数据请求this.getShopList(() => {wx.stopPullDownRefresh()})
}
complete: () => {wx.hideLoading()this.setData({isLoading: false})cb && cb()
}
在 utils 目录下创建 tools.wxs 文件,并创建 splitPhone 方法
function splitPhone(str) {if (str.length !== 11) return strvar arr = str.split('')arr.splice(3, 0, '-')arr.splice(8, 0, '-')return arr.join('')
}module.exports = {splitPhone: splitPhone
} 在 shoplist.wxml 文件中导入 tools.wxs 文件
使用封装的 splitPhone 方法
电话: {{tools.splitPhone(item.phone)}}
上一篇:计算机网络:数据链路层