目录
内容接上:
第七章、页面导航
7.1 页面导航简述
(1)什么是页面导航(可类比vue中的导航传参)
-- 页面导航指的是页面之间的相互跳转
· <a>链接
· location.href
(2)小程序中实现页面导航的两种方式
-- 声明式导航
·在页面上声明一个<navigator>导航组件
·通过点击<navigator>组件实现页面跳转
-- 编程式导航
· 调用小程序的导航API,实现页面的跳转
· 通过编程式导航跳转到 tabBar 页面
wx.switchTab({
url: '/pages/message/message'
})
· 通过编程式导航跳转到一个<navigator>导航的正常页面组件(所有非tabBar 页面)
wx.navigateTo({
url: '/pages/info/info'
})
7.2 声明式导航
tabBar页面配置——
"tabBar": {
"list": [
{
"pagePath": "pages/home/home",
"text": "首页",
"iconPath": "/images/tabs/home.png",
"selectedIconPath": "/images/tabs/home-active.png"
},
{
"pagePath": "pages/message/message",
"text": "消息",
"iconPath": "/images/tabs/message.png",
"selectedIconPath": "/images/tabs/message-active.png"
},
{
"pagePath": "pages/contact/contact",
"text": "联系我们",
"iconPath": "/images/tabs/contact.png",
"selectedIconPath": "/images/tabs/contact-active.png"
}
]
},
非tabBar也页面配置——
"pages": [
"pages/home/home", //在tabBar配置中配置成tarBar页面
"pages/message/message", //在tabBar配置中配置成tarBar页面
"pages/contact/contact", //在tabBar配置中配置成tarBar页面
"pages/info/info" //非tarBar页面
],
(1)导航到tabBar页面
-- tabBar页面:指的是被配置为tabBar的页面
-- 在使用<navigator>组件跳转到指定的tabBar页面时,需要指定url属性和open-type属性:
·url表示要跳转的页面的地址,必须以' / '开头
·open-type表示跳转tabBar的方式,必须设置为switchTab
//注意url和open-type,/pages/message/message为tabBar页面
<navigator url="/pages/message/message" open-type="switchTab">
导航到消息页面(tabBar页面)
</navigator>
(2)导航到非tabBar页面
-- 非tabBar页面:指的是没有被配置为tabBar的页面
-- 在使用<navigator>组件跳转到指定的tabBar页面时,需要指定url属性和open-type属性:
· url表示要跳转的页面的地址,必须以* / *开头,路径如果带参,以'?'分隔,'&'连接参数
· open-type表示跳转的方式,必须设置为navigate
//注意url和open-type,/pages/info/info为非tabBar页面
<navigator url="/pages/info/info" open-type="navigate"> //不带参
导航到info页面(非tarBar页面)
</navigator>
注意:为了简便,在导航非tabBar页面时*open-type="navigate"*属性可以省略(默认)
(3)后退导航(只针对非tabBar页面)
-- 如果要后退到上一页面或多级页面,则需要指定open-type属性和delta 属性,其中:
·open-type的值必须是navigateBack,表示要进行后退导航
·delta的值必须是数字,表示要后退的层级
//返回上一级(常用返回一级)
<navigator open-type="navigateBack">后退</navigator>
注意:如果只是返回到上一页面,则可以省略dalta属,因为其默认值就是1
7.3 编程式导航
(1)导航到tabBar页面 --> 绑定方法,使用wx.switchTab
-- 调用wx.switchTab(Object object)方法,跳转到tabBar页面。其中Object参数对象的属性列表如下:(导航到tabBar的页面不会携带参数)
参数 | 类型 | 是否必选 | 描述 |
url | string | 必选 | 需要跳转的tabBar页面的路径,路径后不能带参数 |
success | function | 非必选 | 接口调用成功的回调函数 |
fail | function | 非必选 | 接口调用失败的回调函数 |
complete | function | 非必选 | 接口调用结束的回调函数(调用成功、失败都会执行) |
//绑定方法(bindtap相当于click,上一篇文章讲过)
<button bindtap="gotoMessage">跳转Message页面</button>
//方法,导航到tabBar页面
gotoMessage() {
wx.switchTab({
url: '/pages/message/message'
})
},
(2)导航到非tabBar页面
-- 调用wx.navigateTo(Object object)方法,跳转到非tabBar的页面。其中Object 参数对象的属性列表,如下:
参数 | 类型 | 是否必选 | 描述 |
url | string | 必选 | 需要跳转的非tabBar页面的路径,路径后能带参数 |
success | function | 非必选 | 接口调用成功的回调函数 |
fail | function | 非必选 | 接口调用失败的回调函数 |
complete | function | 非必选 | 接口调用结束的回调函数(调用成功、失败都会执行) |
--> 与导航到tabBar页面区别: url路径可以携带参数
<button bindtap="gotoInfo">跳转到info页面</button>
//导航到非tabBar页面的方法
gotoInfo() {
wx.navigateTo({
url: '/pages/info/info' //不带参
})
},
(3)后退导航(只针对非tabBar页面)
-- 调用wx.navigateBack(Object object)方法,可以返回上一页面或多级页面。其中Object参数对象可选的:
属性 | 类型 | 默认值 | 必填 | 描述 |
delta | number | 1 | 非必选 | 返回的页面数,如果delta大于现有页面数,则返回到首页 |
<button bindtap="goBack">后退</button>
goBack() {
wx.navigateBack({
delta: 1
})
},
7.4 导航传参
(1)声明式导航传参(可类比vue的传参)
-- navigate组件的url属性用来指定将要跳转的页面路径。同时,路径后面是可以携带参数的:
·参数与路径之间使用"?"分隔
·参数键值对使用=相连
·不同的参数使用"&"分隔
<navigator url="/pages/info/info?name=zs&age=20"> //带参
跳转到info页面(非tarBar页面)
</navigator>
(2)编程式导航传参
-- 调用wx.navigateTo(Object object)方法,可以携带参数,在URL上:
-- 绑定方法,bindtap
<button bindtap="gotoInfo2">跳转到info页面(非tarBar页面)</button>
gotoInfo2() {
wx.navigateTo({
url: '/pages/info/info?name=ls&gender=男' //带参
})
},
(3)在onLoad中接收导航参数
-- 通过声明式导航传参或者编程式导航传参所携带的参数,可以直接在onLoad事件中直接获取到--->也就是onLoad中的options参数。
-- 为了使这个参数可以在每一个方法中使用,会利用this.setData在data中存储该参数,命名query
//data中存储数据
data: {
// 导航传递过来的参数对象
query: {}
},
//onLoad生命周期获取传过来的参数对象
onLoad: function (options) {
console.log(options)
this.setData({ //利用this.setData修改data中的数据
query: options
})
},
第八章、页面事件
8.1 下拉刷新事件
(1)什么是下拉刷新
-- 下拉刷新是移动端的专有名词,指的是通过手指在屏幕上的下拉滑动操作,从而重新加载页面数据的行为
(2)启用下拉刷新
-- 在页面的.json文件中,设置enablePullDownRefresh为true
"enablePullDownRefresh": true
(3)配置下拉刷新窗口的样式
-- backgroundColor -->下拉刷新窗口的背景颜色,16进制
-- backgroundTextStyle -->下拉刷新loading的样式,仅支持dark和light
"backgroundColor": "#efefef",
"backgroundTextStyle": "dark"
(4)监听下拉刷新的事件
-- 在页面.js文件中,通过onPullDownRefresh()函数即可监听当前页面的下拉刷新事件。
(5)停止下拉刷新
-- 真实情况中,当完成下拉之后loading还会显示,不会消失,所有需要手动隐藏效果。调用wx.stopPullDownRefresh()可以停止当前页面下拉刷新
//当前页面的下拉刷新事件在该生命周期钩子执行
onPullDownRefresh: function () {
//停止当前页面下拉刷新
wx.stopPullDownRefresh()
},
8.2 上拉触底事件
(1)什么是上拉触底
-- 上拉触底是移动端的专有名词,通过手指在屏幕上的上拉滑动操作,从而加载更多数据的行为
(2)监听页面的上拉触底事件
-- 在页面的.js文件中,通过onReachBottom()函数即可监听当前页面的上拉触底事件。
注意:要使用节流防止多次发送请求
(3)对上拉触底进行节流处理
-- data中定义isLoading节流阀
· isLoading中布尔值
· true 当前正在进行数据请求
· false 当前没有进行数据请求
data: {
isloding: false
},
-- 修改isLoading节流阀的值
· 在调用方法时将节流阀设置为true
· 在网络请求的complete回调函数中,将节流阀重置为false
//获取颜色为例子
getColors() {
//首先将节流阀设置为true
this.setData({
isloding: true
})
// 需要展示 loading 效果
wx.showLoading({
title: '数据加载中...'
})
//请求数据
wx.request({
url: 'https://……/api/color',
method: 'get',
success: ({ data: res }) => {
this.setData({
colorList: [...this.data.colorList, ...res.data]
})
},
//数据请求成功/失败,将节流阀设置为false
complete: () => {
wx.hideLoading()
this.setData({
isloding: false
})
}
})
-- 在onReachBottom中判断节流阀的值,从而对数据请求进行节流控制
· 如果节流阀值为true,阻止
· 否则,允许
//在上拉刷新的生命周期钩子函数中
onReachBottom: function () {
//如果节流阀不是false(也就是说数据还在请求中),不放行,不发送多次请求
if (this.data.isloding) return
//true,发送请求
this.getColors()
},
第九章、生命周期
9.1 小程序生命周期
-- 一个对象从创建->运行->销毁的整个阶段,强调的是一个时间段
-- 生命周期函数:是小程序提供的内置函数,会伴随着生命周期,自动按次序执行
-- 作用:允许程序员在特定的时间点,执行某些特定的操作。
9.2 生命周期的分类
-- 在小程序中,生命周期分为两类,分别是:
(1)应用生命周期
·特指小程序从启动->运行->销毁的过程
(2)页面生命周期
·特指小程序中,每个页面的加载->渲染->销毁的过程
注意:其中页面的生命周期范围较小,应用程序的生命周期范围较大
小程序启动->页面A的生命周期->页面B的生命周期->···->小程序结束
9.3 生命周期函数的应用
(1)小程序的应用生命周期函数需要在根目录app.js中进行声明:
onLaunch | 当小程序初始化完成时,会触发 onLaunch(全局只触发一次) |
onShow | 当小程序启动,或从后台进入前台显示,会触发 onShow |
onHide | 当小程序从前台进入后台,会触发 onHide |
(2)使用方法:
App({
//当小程序初始化完成时,会触发 onLaunch(全局只触发一次)
onLaunch(){},
//当小程序启动,或从后台进入前台显示,会触发 onShow
onShow(){},
//当小程序从前台进入后台,会触发 onHide
onHide(){}
})
9.4 页面的生命周期函数
(1)小程序的页面生命周期函数需要在页面的.js文件中进行声明:
onLoad | 监听首次页面加载,只调用1次(常用) |
onReady | 监听页面初次渲染完成,只调用一次(常用) |
onShow | 监听页面显示 |
onHide | 监听页面隐藏 |
onUnload | 监听页面卸载 |
(2)使用方法:
page({
//生命周期函数--监听页面加载
onLoad() {},
//生命周期函数--监听页面初次渲染完成
onReady() {},
//生命周期函数--监听页面显示
onShow() {},
//生命周期函数--监听页面隐藏
onHide() {},
//生命周期函数--监听页面卸载
onUnload() {},
})
第十章、WXS脚本
10.1 WXS脚本概述
(1)应用场景(wxs类似于js)
-- wxml中无法调用在页面的.js中定义的函数,但是,wxml中可以调用wxs中定义的函数,因此,小程序中,wxs的典型应用场景就是过滤器
10.2 基本使用
(1)内嵌wxs脚本
-- wxs代码可以编写wxml文件中的<wxs>标签内,就像html中<script>标签一样
-- <wxs>标签,必须提供module属性,用来指定当前wxs的模块名称
<view>{{m1.toUpper(username)}}</view>
//在wxs中写方法
<wxs module="m1">
module.exports.toUpper = function(str) {
return str.toUpperCase()
}
</wxs>
(2)定义外联的wxs脚本
--wxs 代码还可以编写在以.wxs为后缀名的文件内,就像javascript代码可以编写在以.js为后缀名的文件中
--使用:
在wxml中引入外联的wxs脚本时,必须为<wxs>标签添加module和src属性,
· *module*用来指定模块的名称
· *src*用来指定要引入的脚本的路径,且必须是相对路径
<view>{{m2.toLower(country)}}</view>
//导入外部写好的.wxs方法
<wxs src="../../utils/tools.wxs" module="m2"></wxs>
第十一章、自定义组件
11.1 组件的创建与应用
(1)创建组件(类似Vue中的共享组件和路由)
-- 在项目的根目录中,鼠标右键,创建components -> test文件夹
-- 在新建的components -> test文件夹上,鼠标右键,点击“新建Component"
-- 键入组件的名称之后回车,会自动生成组件对应的4个文件,后缀名分别为.js,.json,.wxml和.wxsSs
(2)引用组件
-- 组件的引用方式分为局部引用和全局引用
· 局部引用:组件只能在当前被引用的页面内使用-->当前页面
· 全局引用:组件可以在每个小程序页面中使用-->多个页面
(3)局部引用--->在页面的.json配置文件中引用组件的方式,叫做局部引用
"usingComponents": {
键(自定义名字):"值(组件路径)"
}
配置之后只有该页面可是使用配置的组件
(4)全局引用-->在app.json 全局配置文件中引用组件的方式,叫做“全局引用”,所有页面都能使用
"usingComponents": {
键(自定义名字):"值(组件路径)"
}
"usingComponents": {
"my-test1": "/components/test/test",
"my-test2": "/components/test2/test2",
"my-test3": "/components/test3/test3",
"my-test4": "/components/test4/test4",
"my-test5": "/components/test5/test5"
}
(5)组件与页面的区别
-- 组件与页面的.js和.json文件不相同
·组件的.json文件需要声明"component": true;页面不需要声明
·组件的.js文件中调用的是Component()函数;页面是page()函数
·组件的事件处理函数需要定义到methods节点中;页面是直接定义方法
11.2 样式
(1)组件样式隔离(相当于scoped)
优点:防止外界的样式影响组件内部的样式;防止组件的样式破环外界的样式
(2)组件样式隔离的注意点
-- app.wxss中的全局样式对组件无效
-- 只有class选择器有样式隔离的效果,id选择器、属性选择器、标签选择器不受样式隔离的影响。所以在写样式时,尽量都使用class选择器
(3)修改组件的样式隔离选项
-- 自定义组件的样式隔离特性能够防止组件内外样式互相干扰的问题。为了解决外部能够控制组件内部的样式,可以通过styleIsolation修改组件的样式隔离选项
用法一:
Component({
options: {
styleIsolation: 'islated/apply-shared/shared'
},
})
用法二:组件的.json文件中新增如下配置
{ "styleIsolation":'islated/apply-shared/shared' }
---styleIsolation的三个可选值
islated | 表示启用样式隔离,组件内外使用class指定样式不会相互影响,默认值 |
apply-shared | 表示*页面wxss样式将影响到自定义组件*,但是自定义组件不会影响页面样式 |
shared | 互相影响 |
11.3 数据、方法和属性
(1)data数据
-- 在小程序组件中,用于组件模板渲染的私有数据,需要定义到data节点中
(2)methods方法
-- 在小程序组件中,事件处理函数和自定义方法需要定义到methods节点中
-- 注意:区分事件处理函数(正常定义)和自定义方法(以下划线开头)
(3)properties属性(类似Vue中的props)
-- 在小程序组件中,properties是组件的对外属性,用来接收外界传递到组件中的数据
· 简化的方式,无法设置默认值
· 完整定义
properties: {
// 第一种方式:简化的方式
// '自定义名':数据类型
max: Number
// 第二种方式:完整的定义方式
/*
自定义名:{
type:数据类型,
value:默认值
}
*/
max: {
type: Number,
value: 10 //设置默认值
}
},
· 获取:this.properties.xxx
//this.properties.自定义的名字
this.properties.max
(4)data和properties的区别
-- 小程序的组件中,properties属性和data数据的用法相同,它们都是可读可写的,只不过:
· data更倾向于存储组件的私有数据
· properties更倾向于存储外界传递到组件中的数据
(5)使用setData修改properties的值
-- 由于data数据和properties属性在本质上没有任何区别,因此 properties属性的值也可以用于页面渲染,或使用setData为properties 中的属性重新赋值
this.setData({
count: this.data.count + 1, //对data中的数据进行更新
max: this.properties.max + 1 //对properties中的数据进行更新
})
11.4 数据监听器
(1)什么是数据监听器(类似Vue中的watch)
-- 数据监听器用于监听和响应任何属性和数据字段的变化,从而执行特定的操作。它的作用类似于vue中的watch侦听器。
(2)数据监听器基本用法
添加observers:{'监听对象':function(新的监听对象){对其执行一些事}},
observers:{
'n1,n2':function(newN1,newN2){
this.setData({
sum:newN1+newN2
})
}
}
(3)监听对象属性的变化
data: {
_rgb: {
r: 0,
g: 0,
b: 0
},
fullColor: '0, 0, 0'
},
-- 数据监听器支持监听对象中单个或多个属性的变化,示例语法如下:
observers:{
'对象.属性A,对象.属性B':function(属性A的新值,属性B的新值){
对其执行一些事
}
}
observers: {
'_rgb.r, _rgb.g, _rgb.b': function (r, g, b) {
this.setData({
fullColor: `${r}, ${g}, ${b}`
})
},
},
(4)监听对象中所有属性的变化
--如果某个对象中需要被监听的属性太多,为了方便,可以使用通配符"**"来监听对象中所有属性的变化,**最后获取的是一整个对象里的值
*'rgb.**':function(obj)*
observers: {
'_rgb.**': function (obj) {
this.setData({
fullColor: `${obj.r}, ${obj.g}, ${obj.b}`
})
}
},
11.5 纯数据字段
(1)什么是纯数据字段-->中介值
-- 概念:纯数据字段指的是那些不用于界面渲染的data字段
(2)使用规则
-- 在Component构造器的options节点中,指定pureDataPattern为一个正则表达式,字段名符合这个正则表达式的字段将成为纯数据字段。
-- option中配置pureDataPattern:/^_/
//配置如下
options: {
pureDataPattern: /^_/
},
-- 配置之后,所有纯数据字段,以_开头,例如:_rgb
11.6 组件的生命周期
(1)组件的全部生命周期函数(components文件下的组件的.js文件)
生命周期函数 | 参数 | 描述说明 |
created | 无 | 在组件实例刚刚被创建时执行 |
attached | 无 | 在组件实例进入页面节点树时执行 |
ready | 无 | 在组件在视图层布局完成后执行 |
moved | 无 | 在组件实例被移动到节点树另一个位置时执行 |
detached | 无 | 在组件实例被从页面节点树销毁时执行 |
error | object Error | 每当组件方法抛出错误时执行 |
(2)组件的主要生命周期函数
-- 在小程序组件中,最重要的生命周期函数有3个,分别是created、attached、detached。它们各自的特点如下∶
-- 组件实例刚被创建好的时候,created生命周期函数会被触发
· 此时还不能调用setData
· 通常在这个生命周期函数中,只应该用于给组件的this添加一些自定义的属性字段
-- 在组件完全初始化完毕、进入页面节点树后,attached 生命周期函数会被触发(类似mounted)
· 此时,this.data已被初始化完毕
· 这个生命周期很有用,绝大多数初始化的工作可以在这个时机进行(例如发请求获取初始数据)
-- 在组件离开页面节点树后,detached生命周期函数会被触发(类似Vue中的beforDestory)
· 退出一个页面时,会触发页面内每个自定义组件的detached生命周期函数此时
· 适合做一些清理性质的工作
(3)lifetimes节点
-- 在小程序组件中,生命周期函数可以直接定义在Component构造器的第一级参数中,可以在lifetimes字段内进行声明(这是推荐的方式,其优先级最高)。
lifetimes:{
created(){}
attached(){}
ready(){}
moved(){}
detached(){}
}
11.7 组件所在页面的生命周期
(1)什么是组件所在页面的生命周期
-- 自定义组件的行为依赖于页面状态的变化,此时就需要用到组件所在页面的生命周期。
-- 组件所在页面的生命周期函数有3个,分别是:
生命周期函数 | 参数 | 描述 |
show | 无 | 组件所在的页面被展示时执行 |
hide | 无 | 组件所在的页面被隐藏时执行 |
resize | object Size | 组件所在的页面尺寸变化时执行 |
(2)pageLifetimes节点
-- 组件所在页面的生命周期函数,需要定义在pageLifetimes节点中
pageLifetimes: {
show() {
console.log('show')
},
hide() {
console.log('hide')
},
resize(size) {
console.log('resize',size)
}
}
11.8 插槽
(1)什么是插槽(类比vue中的slot)
-- 在自定义组件的wxml结构中,可以提供一个<slot>节点(插槽),用于承载组件使用者提供的wxml结构。
(2)单个插槽
-- 在小程序中,默认每个自定义组件中只允许使用一个<slot>进行占位,这种个数上的限制叫做单个插槽。
<view>
<slot></slot>
</view>
(3)启用多个插槽
-- 在小程序的自定义组件中,需要使用多<slot>插槽时,可以在组件的.js文件中,通过multipleSlots:true启用
Component({
options:{
multipleSlots:true
},
})
(4)定义多个插槽
-- 可以在组件的.wxml中使用多个<slot>标签,以不同的name来区分不同的插槽。
//组件的wxml中
<view>
<slot name="before"></slot>
<view>这里是组件的内容结构</view>
<slot></slot>
<slot name="after"></slot>
</view>
-- 使用组件时:
<my-test4>
<view>这是通过插槽插入</view>
<view slot="before">这里是插多个插槽的地方befor</view>
<view slot="after">这里是插多个插槽的地方after</view>
</my-test4>
--得到的效果
11.9 父子组件之间的通信
(1)父子组件之间的三种通信方式
-- 属性绑定
· 用于父组件向子组件的指定属性设置数据,仅能设置JSON兼容的数据
-- 事件绑定
· 用于子组件向父组件传递数据,可以传递任意数据
-- 获取组件实例
· 父组件还可以通过this.selectComponent()获取子组件实例对象
· 这样就可以直接访问子组件的任意数据和方法
(2)属性绑定(父->子传数据)
-- 属性绑定用于实现父向子传值,而且只能传递普通类型的数据,无法将方法传递给子组件。
· 父组件做的事
data: {
count:1
}
<view>~~~父组件~~~</view>
<view>父组件中的count值是{{count}}</view>
<view>~~~子组件~~~</view>
<my-test count="{{count}}" class="sc" id="sc"></my-test>
· 子组件做的事
//接收父组件传的值
properties: {
count:Number
},
(3)事件绑定(子向父传数据)
-- 事件绑定用于实现子向父传值,可以传递任何类型的数据。使用步骤如下:
data: {
count:1
}
· 在父组件的js中,定义一个函数,这个函数即将通过自定义事件的形式,传递给子组件
//父组件定义syncCount方法,之后将该方法传给子组件
syncCount(){
console.log('syncCount')
},
· 在父组件的wxml 中,通过自定义事件的形式,将步骤1中定义的函数引用,传递给子组件
<view>~~~父组件~~~</view>
<view>父组件中的count值是{{count}}</view>
<view>~~~子组件~~~</view>
<my-test5 count="{{count}}" bind:sync="syncCount" class="sc" id="sc"></my-test5>
· 在子组件的js 中,通过调用this.triggerEvent('自定义事件名称',{/*参数对象*/}),将数据发送到父组件
//接收父组件传的值
properties: {
count: Number
},
//子组件修改数据,之后将数据返回父组件
addCount(){
//修改子组件数据
this.setData({
count:this.properties.count+1
})
// 触发父组件传过来的自定义事件,将数据发送到父组件
this.triggerEvent('sync',{value:this.properties.count})
}
· 在父组件的js 中,通过e.detail.value获取到子组件传递过来的数据
// 定义一个接收子组件数据的方法
syncCount(e){
console.log("自定义事件的参数",e)
this.setData({
//e.detail.value,获取子组件传过来的值
count:e.detail.value
})
},
-- 自定义事件-->使用bind:自定义事件名称
(4)获取组件实例(子父之间通过组件选择器任意传值)
-- 可在父组件里调用this.selectComponent("id或class选择器"),获取子组件的实例对象,从而直接访问子组件的任意数据和方法。调用时需要传入一个选择器,
· 例如 child = this.selectComponent("#sc"),之后可以访问子组件中所有的方法和属性(包括原型链中)
// 获取子组件实例,子组件中的所有方法
getChild() {
const child = this.selectComponent('#sc')
console.log(child)
child.addCount()
},
11.10 behaviors(插件)
(1)什么是behavior
-- behaviors是小程序中,用于实现组件间代码共享的特性,类似于vue 中的mixins。
(2)behaviors的工作方式
-- 每个 behayior可以包含一组属性、数据、生命周期函数和方法。组件引用它时,它的属性、数据和方法会被合并到组件中。
(3)创建behaviors
-- 根目录下新建一个behavior文件夹,装所有需要共享的代码
-- 调用Behavior(Object object)方法即可创建一个共享的behavior实例对象,并向外暴露
module.exports = Behavior({
data: {
username: 'zs'
},
properties: {},
methods: {},
……
})
(4)导入并使用behavior
-- 在组件中,使用require()方法导入需要的 behavior,组件内使用behaviors挂载后即可访问behavior中的数据或方法
//引入需要的behaviors
const myBehavior = require('../../behaviors/my-behavior')
Component({
//挂载
behaviors: [myBehavior],
})
(5)behavior中所有可用的节点
可用的节点 | 类型 | 是否必填 | 描述 |
properties | object Map | 否 | 同组件的属性 |
data | object | 否 | 同组件的数据 |
methods | object | 否 | 同自定义组件的方法 |
behaviors | string Array | 否 | 引入其它的behavior |
created | Function | 否 | 生命周期函数 |
attached | Function | 否 | 生命周期函数 |
ready | Function | 否 | 生命周期函数 |
moved | Function | 否 | 生命周期函数 |
detached | Function | 否 | 生命周期函数 |
第十二章、使用npm包
12.1 概述
(1)小程序对npm的支持与限制
-- 目前,小程序中已经支持使用npm安装第三方包,从而来提高小程序的开发效率。但是,在小程序中使用npm包有如下3个限制:
·不支持依赖于Node.js内置库的包
·不支持依赖于浏览器内置对象的包
·不支持依赖于C++插件的包
12.2 Vant Weapp(第三方组件库)
(1)什么是Vant Weapp
-- Vant weapp是有赞前端团队开源的一套小程序UI组件库,助力我们快速搭建小程序应用。它所使用的是MIT开源许可协议,对商业使用比较友好。
(2)安装Vant组件库
-- 在小程序项目中,安装Vant组件库主要分为如下3步:
·通过npm安装(建议指定版本为@1.3.3)
右键-->内部终端打开-->npm init -y(初始化)-->npm i @vant/weapp@1.3.3 -S --production
·构建npm包:工具-->构建npm包
·修改app.json:去除"style": "v2";
(3)使用Vant组件
-- 安装完Vant组件库之后,可以在 app.json的usingComponents 节点中引入需要的组件,即可在wxml 中直接使用组件。
"usingComponents": {
"van-button": "@vant/weapp/button/index",
"van-tabbar": "@vant/weapp/tabbar/index",
"van-tabbar-item": "@vant/weapp/tabbar-item/index",
},
(4)定制全局主题样式
-- 在app.wxss中,找到要改的元素,写入CSS变量
page{
--button-danger-background-color:#c00000;
--button-danger-border-color:#D60000;
}
-- 注意:定义CSS变量方式:以--开头
-- 样式修改查看文档:
12.3 API Promise化
(1)基于回电函数的异步API的缺点
-- 默认情况下,小程序官方提供的异步API都是基于回调函数实现的,例如,网络请求的API需要按照如下的方式调用:
wx.request({
url: '', //路径
method:'', //请求方法
data:'', //参数
success:()=>{}, //成功时回调
fail:()=>{}, //失败时回调
complete:()=>{} //完成时回调
})
缺点:容易造成回调地狱的问题,代码可读性、维护性差
(2)什么时API Promise化
APl Promise化,指的是*通过额外的配置*,将官方提供的、基于回调函数的异步API,*升级改造为基于Promise的异步API*,从而提高代码的可读性、维护性,避免回调地狱的问题。
(3)如何实现API Promise化
-- 在小程序中,实现 APl Promise化主要依赖miniprogram-api-promise这个第三方的npm包。
-- npm i -S miniprogram-api-promise@1.0.4
-- 之后需要重新构建npm包
· 在小程序入口文件中(app.js),只需调用一次promisifyAll()方法
· 引用
//导入 promisifyAl1()方法
import {promisifyAll} from 'miniprogram-api-promise'
const wxp = wx.p = {}
promisifyAll(wx,wxp)
(4)调用Promise化之后的异步API
<!--页面的.wxml,绑定事件方法getPInfo-->
<van-button type="primary" bindtap="getPInfo">主要按钮</van-button>
//定义getPInfo方法,之后所有的wx.xxx 都修改成 wx.p.xxx
// 调用Promise化之后的异步API
async getPInfo(){
const {data:res} = await wx.p.request({
url:'https://xxx/api/get',
method:'GET',
data:{
name:'xx',
age:18
}
})
console.log("调用Promise化之后的异步API",res)
},
12.4 全局数据共享(MobX)
(1)什么是全局数据共享(Vue中的Vuex)
-- 全局数据共享(又叫做:状态管理)是为了解决组件之间数据共享的问题。
(2)小程序中的全局数据共享方案
-- 在小程序中,可使用mobx-miniprogram配合mobx-miniprogram-bindings实现全局数据共享。
·mobx-miniprogram用来创建Store实例对象(类似先下载vuex包)
·mobx-miniproaram-bindings用来把Store中的共享数据或方法,绑定到组件或页面中使用(创建小仓库)
(3)安装MobX相关的包
(1)安装
npm i -S mobx-miniprogram@4.13.2 mobx-miniprogram-bindings@1.2.1
(2)引用
import {observable} from 'mobx-miniprogram'
(4)store中的常用方法
-- 数据字段
export const store = observable({
numA:1,
numB:2,
})
-- 计算属性(get属性)
export const store = observable({
// 计算属性
get sum(){
return this.numA+this.numB
},
})
-- action方法,专门用来修改store中数据
export const store = observable({
// action方法,用来修改store中数据
updataNum1:action(function (params) {
this.numA += params
}),
updataNum2:action(function (params) {
this.numB += params
}),
})
(5)将Store中的成员绑定到页面中
-- 导入对应的文件
import {createStoreBindings} from 'mobx-miniprogram-bindings'
import {store} from '../../store/store'
-- 在页面.js文件onLoad生命周期函数引入共享数据
onLoad(options) {
this.storeBindings = createStoreBindings(this,{
store,
fields:['numA','numB','sum'],
actions:['updataNum1','updataNum2']
})
},
-- 在页面的.js文件的onUnload生命周期函数注销
onUnload() {
this.storeBindings.destroyStoreBindings()
},
(6)在页面使用Store中的成员
-- 数据和计算属性(field中的所有值):可以直接在页面上使用
-- 方法(actions):则是绑定事件后在当前.js文件调用
(7)将Store中的成员绑定到组件中-->组件中
-- 导入对应的包
import {storeBindingsBehavior} from 'mobx-miniprogram-bindings'
import {store} from '../../store/store'
-- 通过storeBindingsBehavior实现自动绑定
Component({
behaviors:[storeBindingsBehavior],
})
-- 使用storeBindings获取共享的数据源
storeBindings:{
//数据源
store, //指定要绑定的Store
fields:{ //指定要绑定的字段数据
// 自定义名字:'共享数据的名字'
numA:()=>store.numA, //绑定字段的第1种方式
numB:(store)=>store.numB, //绑定字段的第2种方式
sum:'sum' //绑定字段的第3种方式
},
actions:{ //指定要绑定的方法
updataNum2:'updataNum2'
}
},
(8)在页面使用Store中的成员
-- 数据和计算属性(field中的所有值):可以直接在组件上使用
-- 方法(actions):则是绑定事件后在当前.js文件的methods中的函数调用
第十三章、分包
13.1 基础概念
(1)什么是分包
-- 分包指的是把一个完整的小程序项目,按照需求划分为不同的子包,在构建时打包成不同的分包,用户在使用时实现按需进行加载。
(2)分包的好处
-- 可以优化小程序首次启动的下载时间
-- 在多团队共同开发时可以更好的解耦协作
(3)分包前项目的构成
-- 分包前,小程序项目中所有的页面和资源都被打包到了一起,导致整个项目体积过大,影响小程序首次启动的下载时间。
(4)分包后的项目构成
-- 分包后,小程序项目由1个主包+多个分包组成:
-- 主包:一般只包含项目的启动页面或TabBar页面、以及所有分包都需要用到的一些公共资源
-- 分包:只包含和当前分包有关的页面和私有资源
(5)分包的加载规则
-- 小程序启动时,默认会下载主包并启动主包内的页面
·tabBar页面需要放到主包中
-- 当用户进入分包内的某个页面,客户端会把对应的分包下载下来,下载完成后再进行展示
·非tabBar页面可以按照功能的不同,划分为不同的分包之后,进行按需下载
(6)分包体积限制
-- 目前小程序的大小有一下两个限制:
·整个小程序所有非分包大小,不超过16M(主包+所有分包)
·单个分包/主包大小不能超过2M
13.2 使用分包
(1)使用目的:小程序项目中所有的页面和资源都被打包到了一起,导致整个项目体积过大,影响小程序首次启动的下载时间,使用分包之后能按需加载,优化
配置方法:app.json添加配置项subPackages——
"subPackages": [
{
"root": "pagA", //根目录
"name": "p2", //给该包命名代替
"pages": [
"pages/cat/cat", //根目录下的分包
"pages/dog/dog"
]
},
{},
……,
{}
]
(2)分包的打包原则
-- 小程序会按subpackages的配置进行分包,subpackages之外的目录将被打包到主包中
-- 主包也可以有自己的 pages(即最外层的pages字段)
-- tabBar页面必须在主包内
-- 分包之间不能互相嵌套
(3)引用原则
-- 主包无法引用分包内的私有资源
-- 分包之间不能相互引用私有资源
-- 分包可以引用主包内的公共资源
13.3 独立分包
(1)什么是独立分包
-- 独立分包本质上也是分包,只不过它比较特殊,可以独立于主包和其他分包而单独运行
(2)独立分包和普通分包的区别
最主要的区别是:是否依赖于主包才能运行
-- 普通分包必须依赖于主包才能运行
-- 独立分包可以在不下载主包的情况下,独立运行
(3)独立分包的应用场景
-- 开发者可以按需,将某些具有一定功能独立性的页面配置到独立分包中。原因如下:
· 当小程序从普通的分包页面启动时,需要首先下载主包
· 而独立分包不依赖主包即可运行,可以很大程度上提升分包页面的启动速度
注意:一个小程序可以有多个独立分包
(4)独立分包的配置方法
-- 与普通分包配置一样,但是区别在于,独立分包需要添加配置项:"independent": true
"subPackages": [
//独立分包
{
"root": "pagB",
"name": "p2",
"pages": [
"pages/apple/apple"
],
//配置独立分包
"independent": true
}
],
(5)引用原则
-- 独立分包和普通分包以及主包之间,是相互隔绝的,不能相互引用彼此的资源!
·主包无法引用独立分包内的私有资源
·独立分包之间,不能相互引用私有资源
·独立分包和普通分包之间,不能相互引用私有资源
·特别注意:独立分包中不能引用主包内的公共资源(与普通分包的区别)