什么是页面导航
页面导航指的是页面之间的相互跳转,例如,在浏览器中实现页面导航的方式有如下两种:
a
标签location.href
小程序中实现页面导航的两种方式
声明式导航
导航组件
组件实现页面跳转编程式导航
API
,实现页面的跳转tabBar
页面指的是被配置为 tabBar
的页面
在使用
组件跳转到指定的 tabBar
页面时,需要指定 url
属性和 open-type
属性,其中:
url
表示要跳转的 页面的地址
,必须以 /
开头open-type
表示 跳转的方式
,必须为 switchTab
非 tabBar 页面
指的是没有被配置为 tabBar
的页面
在使用
组件跳转到普通的非 tabBar
页面时,则需要指定 url
属性和 open-type
属性,其中:
url
表示要跳转的 页面的地址
,必须以 /
开头open-type
表示 跳转的方式
,必须为 navigate
如果要后退到上一页面或多级页面,则需要指定 open-type
属性和 delta
属性,其中
open-type
的值必须是 navigateBack
,表示要进行后退导航delta
的值必须是数字,表示要后退的层级调用 wx.switchTab(Object object)
方法,可以跳转到 tabBar
页面,其中 Object
参数对象的属性列表如下:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
url | string | 是 | 需要跳转的 tabBar 页面的路径 ,路径后不能带参数。 |
success | function | 否 | 接口调用成功的回调函数 |
fail | function | 否 | 接口调用失败的回调函数 |
complete | function | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
示例代码:
调用 wx.navigateTo(Object object)
方法,可以跳转到非 tabBar
的页面。其中 Object
参数对象的属性列表如下
属性 | 类型 | 必填 | 说明 |
---|---|---|---|
url | string | 是 | 需要跳转的应用内非 tabBar 的页面的路径 , 路径后可以带参数 |
success | function | 否 | 接口调用成功的回调函数 |
fail | function | 否 | 接口调用失败的回调函数 |
complete | function | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
示例代码:
调用 wx.navigateBack(Object object)
方法,可以返回上一页面或多级页面。其中 Object
参数对象可选的属性列表如下:
属性 | 类型 | 默认值 | 必填 | 说明 |
---|---|---|---|---|
delta | number | 1 | 否 | 返回的页面数,如果 delta 大于现有页面数,则返回到首页。 |
success | function | 否 | 接口调用成功的回调函数 | |
fail | function | 否 | 接口调用失败的回调函数 | |
complete | function | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
示例代码:
navigator
组件的 url
属性用来指定将要跳转到的页面的路径。同时,路径的后面还可以携带参数
:参数
与 路径
之间使用 ?
分隔
参数键
与 参数值
用 =
相连不同参数
用 &
分隔下拉刷新
是移动端的专有名词,指的是通过手指在屏幕上的下拉滑动操作,从而 重新加载页面数据
的行为在开启下拉刷新以后,如何不手动停止下拉,下拉动作会一直存在,不会弹回去
在模拟器中会弹回去,在真机上不会弹回去
启动下拉刷新的三种方式
全局开启下拉刷新
app.json
的 window
节点中,将 enablePullDownRefresh
设置为 true
局部开启下拉刷新
.json
配置文件中,将 enablePullDownRefresh
设置为 true
使用小程序提供的 API 实现下拉刷新
wx.startPullDownRefresh()
在实际开发中,推荐使用第 2 种方式,为需要的页面单独开启下拉刷新的效果
在全局或页面的 .json
配置文件中,通过 backgroundColor
和 backgroundTextStyle
来配置下拉刷新窗口的样式,其中
backgroundColor
用来配置下拉刷新 窗口的背景颜色
,仅支持 16 进制的颜色值backgroundTextStyle
用来配置下拉刷新 loading
的样式,仅支持 dark
和 light
在页面的 .js
文件中,通过 onPullDownRefresh()
函数即可监听当前页面的下拉刷新事件
案例1:在页面的 wxml
中有如下的 UI
结构,点击按钮可以让 count
值自增 +1
案例2:在触发页面的下拉刷新事件的时候,如果要把 count
的值重置为 0,示例代码如下:
当处理完下拉刷新后,下拉刷新的 loading
效果会一直显示,不会主动消失
, 所以需要手动隐藏 loading
效果,此时,调用 wx.stopPullDownRefresh()
可以停止当前页面的上拉刷新
示例代码:
上拉触底是移动端的专有名词,通过手指在屏幕上的上拉滑动操作,从而加载更多数据的行为
触发上拉触底事件时,滚动条距离页面底部的距离
.json
配置文件中,通过 onReachBottomDistance
属性来配置上拉触底的距离50px
,在实际开发中,可以根据自己的需求修改这个默认值(Life Cycle)
是指一个对象从 创建 -> 运行 -> 销毁 的整个阶段,强调的是一个时间段启动
,表示 生命周期的开始
关闭
,表示 生命周期的结束
应用生命周期
页面生命周期
注意:页面的生命周期范围较小,应用程序的生命周期范围较大
小程序框架提供的内置函数,会伴随着生命周期,自动按次序执行
生命周期函数的作用:
注意:生命周期强调的是时间段,生命周期函数强调的是时间点。
小程序中的生命周期函数分为两类,分别是:
应用生命周期函数
页面生命周期函数
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) {
}
})
每个小程序页面,必须拥有自己的 .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 () {
}
})
wxs
什么是 wxs
WXS (WeiXin Script)
是小程序的一套脚本语言,结合 WXML
,可以构建出页面的结构wxs
的应用场景
wxs
的 典型应用场景
就是 过滤器
虽然 wxs
的语法类似于 JavaScript
,但是 wxs
和 JavaScript
是完全不同的两种语言
wxs
有自己的数据类型
number
数值类型string
字符串类型boolean
布尔类型object
对象类型function
函数类型array
数组类型date
日期类型regexp
正则wxs
不支持类似于 ES6
及以上的语法形式
JavaScript: DOM、BOM、ECMAScript
wxs
遵循 CommonJS
规范
module
对象:module.export
require
函数wxs
遵循 CommonJS
模块化规范
CommonJS
是javascript
的模块化规范之一,小程序的脚本语言wxs
遵循了CommonJS
规范,因此,使用wxs
时的体验和使用node.js
的体验比较相似。
module
对象
wxs
都是独立的模块,每个模块均有一个内置的 module 对象,每个模块都有自己独立的作用域。module.exports
wxs
拥有独立作用域,所以在一个模块里面定义的变量与函数,默认为私有的,对其他模块不可见,module.exports
属性,可以对外共享本模块的私有变量与函数。require函数
wxs
模块中引用其他 wxs
文件模块,可以使用 require
函数。使用的规则
wxs
代码可以编写在 wxml
文件中的
标签内,就像 javascript
代码可以编写在 html
文件中的
标签内一样。wxml
文件中的每个
标签,必须提供一个 module
属性,用来指定当前
标签的模块名。在单个 wxml
文件内,建议其值唯一。案例代码
在 wxml
中如果要引入外联的 wxs
脚本,必须为
标签添加 module
和 src
属性
module
用来为
标签指定模块名,作为当前页面访问这个模块的标识名称src
用来指定当前
标签要引入的脚本路径,必须是相对路径
示例代码
没有兼容性
wxs
不依赖于运行时的基础库版本,可以在所有版本的小程序中运行
与 javascript
不同
为了降低 wxs
的学习成本, wxs
语言在设计时大量借鉴了 JavaScript
语法
但本质上,wxs
与 javascript
是不同的语言,有自己的语法,并不和 javascript
一致
隔离性
wxs
的运行环境和其他 javascript
代码是隔离的
wxs
中不能调用其他 javascript
文件中定义的函数API
不能作为事件回调
性能好
iOS
设备上比 javascript
运行快
由于运行环境的差异,在 iOS
设备上小程序内的 wxs
会比 javascript
代码快 2 ~ 20 倍。
在 android
设备上二者运行效率无差异
打开微信开发者工具 --> 点击 项目
--> 导入项目
--> 选择项目目录
--> 如有必要,需要替换 AppID
创建页面路径
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>
在 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
表示每页请求几条数据响应参数
header
字段中案例代码
data: {
query: {
},
shoplist: [], // 商铺列表数组
page: 1, // 页码
pagesize: 10, // 每页请求的数量
total: 0 // 总条数
}
定义获取商品数据的方法,并将数据赋值给 data
中的 shoplist
以及 total
getShopList() {
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()
}
<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>
<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;
}
在网络请求发起之前调用 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()
}
})
}
配置页面触底的距离
{
"usingComponents": {
},
"onReachBottomDistance": 100
}
在 onReachBottom
事件处理程序中处理逻辑
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
this.setData({
page: this.data.page + 1
})
this.getShopList()
}
对上拉触底进行节流处理
在 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()
}
如果下面的公式成立,则证明没有下一页数据了:
页码值 * 每页显示多少条数据 >= 总数据条数
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) return
this.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 str
var arr = str.split('')
arr.splice(3, 0, '-')
arr.splice(8, 0, '-')
return arr.join('')
}
module.exports = {
splitPhone: splitPhone
}
在 shoplist.wxml
文件中导入 tools.wxs
文件
<wxs src="../../utils/tools.wxs" module="tools"></wxs>
使用封装的 splitPhone
方法
电话: {
{tools.splitPhone(item.phone)}}
问题
小程序如果需要发起网络请求,必须在 服务器域名中对域名进行配置,
小程序会往配置域名中发起请求,
但是,我们并没有在后台配置服务器域名,所以在手机上访问不了
解决方案
vConsole
,会显示页面的结构,以及 log 等,在实际开发中,可以配置模拟器进行测试如有不足,请多指教,
未完待续,持续更新!
大家一起进步!