04
页面导航
- 声明式导航
- 在页面上声明一个
<navigator>
导航组件 - 通过点击
<navigator>
组件实现页面跳转
- 在页面上声明一个
- 编程式导航
- 调用小程序的导航API,实现页面的跳转
声明式导航
导航到tabBar页面
tabBar页面指的是被配置为tabBar的页面。
在使用<navigator>
组件跳转到指定的tabBar 页面时,需要指定url
属性和open-type
属性,其中:
- `url`表示要跳转的**页面的地址**,必须以 `/` 开头
- `open-type` 表示**跳转的方式**,必须为`switchTab`
在普通页面中实现点击跳转:
<navigator url="/pages/04buton/04buton">导航到04页面</navigator>
在tabBar页面中实现点击跳转:
<navigator url="/pages/11tabUser/11tabUser" open-type="switchTab">点击跳转到User</navigator>
导航到非tabBar页面
非tabBar页面:没有被配置为tabBar的页面
在使用<navigator>
组件跳转到普通的非tabBar 页面时,则需要指定url
属性和open-type
属性,其中:
url
表示要跳转的页面的地址,必须以/
开头open-type
表示跳转的方式,必须为navigate
为了简便,在导航到非
tabBar
页面时,open-type="navigate"
属性可以省略。
<!-- 跳转到非tabBar页面 -->
<navigator url="/pages/05image/05image" open-type="navigate">点击跳转到05image页面</navigator>
后退导航
如果要后退到上一页面或多级页面,则需要指定
open-type
属性和delta
属性,
-
open-type
的值必须是navigateBack
,表示要进行后退导航 -
delta
的值必须是数字,表示要后退的层级不写
delta
则默认为1
<!--pages/05image/05image.wxml-->
<navigator open-type="navigateBack" delta="1">后退</navigator>
编程式导航
导航到tabBar页面
调用wx.switchTab(Object object)
方法,可以跳转到tabBar页面。其中Object参数对象的属性列表如下:
<!-- 编程式导航 -->
<view>编程式导航</view>
<button bindtap="gotoUser" type="default">跳转到tbaUser</button>
// 通过编程式导航跳转到tbaUser页面
gotoUser() {
wx.switchTab({
url: '/pages/11tabUser/11tabUser',
})
},
导航到非tabBar页面
调用wx.navigateTo(Object object)
方法,可以跳转到非tabBar的页面。其中Object参数对象的属性与上面基本相同
<button bindtap="gotoImage" type="primary">跳转到05image</button>
// 通过编程式导航跳转到非tabBar页面
gotoImage() {
wx.navigateTo({
url: '/pages/05image/05image',
})
},
后退导航
调用wx.navigateBack()
方法
<!--pages/05image/05image.wxml-->
<button bindtap="goBack">点击返回</button>
// 编程式导航
goBack() {
wx.navigateBack() // 包含参数delta默认为1
},
页面事件
下拉刷新
全局开启——app.json
——window节点中
局部开启——页面的.json
文件
'enablePullDownRefresh':true
样式:
backgroundColor
、backgroundTextStyle
(loading样式—dark/light)
监听下拉刷新事件
onPullDownRefresh
<!-- onPullDownRefresh下拉刷新 -->
<view>count值是:{{count}}</view>
<button bindtap="addCount">+1</button>
data: {
count: 0
},
addCount() {
this.setData({
count: this.data.count + 1
})
},
onPullDownRefresh: function () {
// 下拉刷新后count重置为0
console.lo g('onPullDownRefresh')
this.setData({
count: 0
})
wx.stopPullDownRefresh() // 停止下拉刷新
},
停止下拉刷新效果
wx.stopPullDownRefresh()
上拉触底
在页面的.js
文件中,通过onReachBottom()
函数即可监听当前页面的上拉触底事件
在页面的.json
文件中配置onReachBottomDistance
属性配置上拉触底的距离(距离底部多少距离开始调用onReachBottom()
函数)
案例 — 本地生活
-
随机获取随机颜色的方法
data: { colorList: [] }, // 随机颜色 getColor() { wx.request({ url: 'https://www.escook.cn/api/color', method: 'GET', success: ({data:res}) => { // data属性并重命名为res console.log(res) this.setData({ colorList: [...this.data.colorList,...res.data] }) } }) },
-
页面加载时获取初始数据
// 监听页面加载 onLoad: function (options) { this.getColor() },
-
渲染UI并美化页面结果
<view wx:for="{{colorList}}" wx:key="index" class="num-item" style="background-color: rgba({{item}});">{{item}}</view>
.num-item { border: 1rpx solid #efefef; border-radius: 8rpx; line-height: 200rpx; text-align: center; margin: 15rpx; text-shadow: 0rpx 0rpx 5rpx #fff; box-shadow: 1rpx 1rpx 6rpx #aaa; }
-
上拉触底获取随机颜色
// 上拉触底方法 onReachBottom: function () { this.getColor() },
-
添加loading提示效果–
wx.showloading()
|wx.hideloading()
-
上拉触底节流处理
-
在data中定义
isloading
节流阀false
表示当前没有进行任何数据请求true
表示当前正在进 行数据请求
isloading:fale
-
在
getColor()
方法中修改isloading
节流阀的值- 在刚调用
getColors
时将节流阀设置true
- 在网络请求的
complete
回调函数中,将节流阀重置为false
getColor() { this.setData({ isloading: true }) ...... wx.request({ ...... complete: () => { wx.hideLoading() this.setData({ isloading: false }) ......
- 在刚调用
-
在
onReachBottom
中判断节流阀的值,从而对数据请求进行节流控制- 如果节流阀的值为
true
,则阻止当前请求 - 如果节流阀的值为
false
,则发起数据请求
onReachBottom: function () { if(this.data.isloading) return this.getColor() },
- 如果节流阀的值为
-
生命周期
应用生命周期(大)
- 小程序启动->运行->销毁过程
页面生命周期(小)
- 小程序中的页面加载->渲染->销毁过程
生命周期强调时间段,生命周期函数强调的是时间点
生命周期函数分类:
-
应用的生命周期函数 – 在**
app.js
**中进行声明- 小程序从启动->运行->销毁期间依次调用的函数
// app.js App({ // 当小程序初始化完成时,会触发 onLaunch(全局只触发一次) onLaunch: function () {}, // 当小程序启动,或从后台进入前台显示,会触发 onShow onShow: function (options) {}, // 当小程序从前台进入后台,会触发 onHide onHide: function () {}, // 当小程序发生脚本错误,或者 api 调用失败时,会触发 onError 并带上错误信息 onError: function (msg) {} })
-
页面的生命周期函数 – 在页面的**
.js
**中进行声明- 小程序每个页面加载->渲染->销毁期间依次调用的函数
// pages/demo/demo.js Page({ // 页面的初始数据 data: {}, // 生命周期函数--监听页面加载 onLoad: function (options) {}, // 生命周期函数--监听页面初次渲染完成 onReady: function () {}, // 生命周期函数--监听页面显示 onShow: function () {}, //生命周期函数--监听页面隐藏 onHide: function () {}, // 生命周期函数--监听页面卸载 onUnload: function () {}, // 页面相关事件处理函数--监听用户下拉动作 onPullDownRefresh: function () {}, // 页面上拉触底事件的处理函数 onReachBottom: function () {}, // 用户点击右上角分享 onShareAppMessage: function () {} })
WXS 脚本
WXS(WeiXin Script)是小程序独有的一套脚本语言,结合WXML,可以构建出页面的结构。
wxml中无法调用在页面的.js
中定义的函数,但是,wxml中可以调用WXS中定义的函数。因此,小程序中WXS的典型应用场景就是**“过滤器”**。
wxs和JavaScript的关系
-
wxs有自己的数据类型
number string boolean object array function date regexp 数值类型 字符串类型 布尔类型 对象类型 数组类型 函数类型 日期类型 正则 -
wxs不支持类似于ES6以上的语法形式
- 不支持:let、const、解构赋值、展开运算符、箭头函数、对象属性简写、etc……
- 支持:var 定义变量、普通function函数等类似于ES5的语法
-
wxs遵循
CommonJS
规范module
对象require()
函数module.exports
对象
内嵌wxs脚本
wxs代码可以编写在wxml文件中的<wxs>
标签内,就像Javascript
代码可以编写在html文件中的<script>
标签内一样。
wxml文件中的每个<wxs></wxs>
标签,必须提供module
属性,用来指定当前WXS的模块名称,方便在wxml中访问模块中的成员:
原本输出为’zs’,但调用m1后输出为’ZS’。
data: {username:'zs'}, // js
<view>{{m1.toUpper(username)}}</view>
<wxs module="m1">
module.exports.toUpper = function (str) {
return str.toUpperCase()
}
</wxs>
AppData中的数据仍为小写’zs’未改变
定义外联的wxs脚本
wxs代码还可以编写在以.wxs
为后缀名的文件内,就像 javascript
代码可以编写在以.js
为后缀名的文件中一样。
示例:/utils
文件夹下创建tools.wxs
function toLower(str){
return str.toLowerCase()
}
module.exports = {
toLower: toLower // 属性 : 对应的值
}
使用外联的wxs脚本
在wxml中引入外联的wxs脚本时,必须为<wxs>
标签添加module
和src
属性,其中:
module
用来指定模块的名称src
用来指定要引入的脚本的路径,且必须是相对路径
data:{country: 'CHINA'}
<view>{{m2.toLower(country)}}</view>
<wxs src="../../utils/tools.wxs" module="m2"></wxs>
特点
-
为了降低wxs(WeiXin Script)的学习成本、wxs语言在设计时借大量鉴了JavaScript的语法。但是本质上,wxs和JavaScript是完全不同的两种语言!
-
wxs典型的应用场景就是“过滤器”,经常配合
Mustache
语法进行使用。但是,在wxs中定义的函数不能作为组件的事件回调函数。例如:<button bindtap="m2.toLower">按钮</button>
-
隔离性:wxs的运行环境和其他JavaScript代码是隔离的。
- wxs不能调用
js
中定义的函数 - wxs不能调用小程序提供的
API
- wxs不能调用
-
性能好(IOS设备中比JavaScript代码块2~20倍,但Android设备就无差异)
案例–本地生活
页面导航并传参
-
设置页面标题
<!-- 九宫格区域 --> <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>
data: { query: {} }, onLoad: function (options) { // 获取页面参数 this.setData({ query: options }) }, onReady: function () { wx.setNavigationBarTitle({ title: this.data.query.title, }) },
添加编译模式 —— 自定义参数
-
列表页面的API接口
以分页形式加载分类下商铺列表的数据:
-
接口地址
-
https://www.escook.cn/categories/:cate_id/shops
-
URL地址中的:
cate_id
是动态参数,表示分类的id
-
-
请求方式——GET请求
-
请求参数
_page
:请求第几页的数据_limit
:每页请求几条数据
data: { ...... shopList: [], // 所有商铺的信息 page: 1, // 一进入商铺列表就请求第一页的信息 pageSize: 10, // 每页默认获取10条数据 total: 0 // 当前总共数据 }, // 获取商铺列表 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) => { console.log(res) this.setData({ shopList: [...this.data.shopList, ...res.data], total: res.header['X-Total-Count'] - 0 }) } }) }, onLoad: function (options) { // 获取页面参数 this.setData({ query: options }) this.getShopList() },
渲染列表
<!--pages/shoplist/shoplist.wxml--> <view class="shop-item" wx:for="{{shopList}}" wx:key="id"> <view class="thumb"> <image src="{{item.imgaes[0]}}"></image> </view> <view class="info"> <text>{{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; } .info text:nth-child(1){ font-weight: bold; }
-
上拉触底加载下一页数据
判断是否还有下一页数据
如果下面的公式成立,则证明没有下一页数据:
页码值 * 每页显示多少条数据 >= 总数据条数
page * pageSize >= total
案例1:总共有77条数据,如果每页显示10条数据,则总共分为8页,其中第8页只有7条数据
page(7) * pageSize(10) >= total(77)
page(8) * pageSize(10) >= total(80)
案例2:总共有80条数据,如果每页显示10条数据,则总共分为8页,其中第8页面有10条数据
page(7) * pageSize(10) >= total(80)
page(8) * pageSize(10) >= total(80)
添加节流阀
1. // data添加: isloading: false // 添加节流阀
2. getShopList() {
// 节流阀
this.setData({
isloading: true
})
// 展示loading效果
......
complete: () => {
......
// 节流阀
this.setData({
isloading: false
})
......
},
3. onReachBottom: function () {
console.log('onReachBottom')
// 节流阀
if (this.data.isloading) return
this.setData({
page: this.data.page + 1
})
// 获取列表
this.getShopList()
},
下拉刷新列表数据
下拉刷新基本配置
"onReachBottomDistance": 200,
"enablePullDownRefresh": true,
"backgroundTextStyle": "dark",
"backgroundColor": "#efefef"
数据获取成功关闭下拉刷新的动画wx.stopPullDownRefresh()
仅下拉刷新的时候调用
wx.stopPullDownRefresh()
,但直接在getShopList()
获取数据后直接调用就成为下滑加载也会调用wx.stopPullDownRefresh()
,显然不合适。
getShopList(cb)
cb && cb()
cb回调
getShopList(cb) {
......
complete: () => {
......
// 隐藏下拉刷新效果
// wx.stopPullDownRefresh()
cb && cb()
// 节流阀
......
}
......
},
onPullDownRefresh: function () {
......
// 重新发起数据请求
this.getShopList(() => {
wx.stopPullDownRefresh()
})
},
处理文本(手机号)
效果:12345678900 ==> 123-4567-8900
手机号字符串长度为11位
tools.wxs
function splitPhone(str) {
if (str.length != 11) return str
var arr = str.split('')
console.log('phone',arr)
}
module.exports = {
splitPhone: splitPhone
}
打印输出:
**
arr.splice()
**在指定位置删除元素或加入元素
arr.splice(3,0,'-')
第3个位置插入-
arr.splice(8,0,'-')
第8个位置插入-
return arr.join('')
将数组合并
function splitPhone(str) {
if (str.length != 11) return str
var arr = str.split('')
arr.splice(3,0,'-')
arr.splice(8,0,'-')
return arr.join('')
}