目录
实现横向布局效果
实现滚动效果
实现轮播图效果
实现文本长按选中复制效果
渲染 HTML 标签
按钮组件的使用效果
图片组件的使用效果
Mustache 语法
动态绑定内容(定义变量,渲染变量)
动态绑定属性(将属性定义为变量并使用)
使用三元运算
算术运算
事件绑定
触摸事件绑定
触摸事件发生改变 data 中数据的值
为事件处理函数传参
输入事件绑定
实现文本框和 data 之间的数据同步
条件渲染(根据一定条件进行渲染)
使用 block 包装组件(单纯的容器)
列表渲染
导入外联样式表
window 节点常用的配置项
设置导航栏的背景色
设置导航栏的标题内容
设置导航栏的标题颜色
开启下拉刷新效果
设置下拉刷新时窗口的背景色
设置下拉刷新时 loading(加载) 的样式
设置上拉触底的距离(一般默认即可)
下拉刷新
监听用户下拉动作
停止下拉刷新效果(刷新完成,自动停止)
上拉触底
上拉触底案例
tabBar 配置页面跳转标签
配置页面跳转标签 tab
网络数据请求
发起 GET 请求
页面加载时便请求数据
滚动选择器
普通选择器
页面导航
导航到 tabBar 页面
导航到非 tabBar 页面
导航到上一页(后退导航)
页面导航 - 编程式导航
导航到 tabBar 页面
导航到非 tabBar 页面
后退导航
页面导航 - 导航传参
声明式导航传参
编程式导航传参
接收导航参数
生命周期函数
应用生命周期函数
页面生命周期函数
WXS 脚本
内嵌 wxs 脚本
外联 wxs 脚本
通过 wxs 脚本修改电话格式
消息提示框
自定义组件
创建组件文件
局部引入组件
全局引入组件
自定义组件的样式隔离选项
自定义主键的数据和方法定义
自定义组件传参以及参数获取
使用数据监听器
监听对象中指定属性的变化
监听对象中所有属性的变化
纯数据字段
组件的生命周期函数
组件所在页面的生命周期
组件所在页面的生命周期案例
单个插槽
多个插槽
父子组件之间的通信 - 父向子传值
父子组件之间的通信 - 子向父传值
访问子组件的任意数据和方法
组件间代码共享
创建 behavior
导入并使用 behavior
使用 Vant 组件
定制 Vant 组件样式
小程序 api 的 promise 化
调用 Promise 化后的异步 API
全局数据共享
安装 mobx 相关的包
创建 Store 实例
将 store 中的成员绑定到页面中
在页面上使用 store 中的成员
将 store 中的成员绑定到组件中
在组件中使用 store 中的成员
对小程序进行分包
独立分包
配置分包的预下载
自定义 tabBar
1.配置信息
2.添加 tabBar 代码文件
3.根据 Vant 组件来自定义 tabBar
引入组件
基础用法
4.根据 list 数组中定义的属性内容来批量设置 tabBar 效果
5.在自定义组件中使用 Vant 组件,需要覆盖 Vant 组件原来的样式
6.实现 tabBar 页面的切换效果
实现横向布局效果
wxml
<view class="container1"><view>A</view><view>B</view><view>C</view>
</view>
wxss
.container1 view{width: 100px;height: 100px;text-align: center;line-height: 100px;
}/*选择 .container1 类下的第一个 view*/
.container1 view:nth-child(1){background-color: lightgreen;
}
.container1 view:nth-child(2){background-color: lightblue;
}
.container1 view:nth-child(3){background-color: lightpink;
}.container1{display: flex;justify-content: space-around;
}
实现滚动效果
wxml
<!-- scroll-x 属性,允许横向滚动-->
<!-- scroll-y 属性,允许纵向滚动-->
<!-- 注意:使用纵向滚动时,必须给 scroll-view 一个固定高度 -->
<!-- 注意:使用横向滚动时,必须给 scroll-view 一个固定宽度 -->
<scroll-view class="container1" scroll-y><view>A</view><view>B</view><view>C</view>
</scroll-view>
wxss
/*选择 .container1 类下的所有 view*/
.container1 view{width: 100px;height: 100px;text-align: center;line-height: 100px;
}/*选择 .container1 类下的第一个 view*/
.container1 view:nth-child(1){background-color: lightgreen;
}
.container1 view:nth-child(2){background-color: lightblue;
}
.container1 view:nth-child(3){background-color: lightpink;
}.container1{border:1px solid red;/* 给 scroll-view 固定高度 */height: 120px;width: 100px;
}
实现轮播图效果
wxml
<!--pages/list/list.wxml-->
<!-- 轮播图的结构 -->
<swiper class="swiper-container" indicator-dots autoplay interval="1000" circular><!-- 第一个轮播图 --><swiper-item><view class="item">A</view></swiper-item><!-- 第二个轮播图 --><swiper-item><view class="item">B</view></swiper-item><!-- 第三个轮播图 --><swiper-item><view class="item">C</view></swiper-item>
</swiper>
wxss
/* pages/list/list.wxss */
.swiper-container{height: 150px;
}.item{height: 100%;line-height: 150px;text-align: center;
}.swiper-container swiper-item:nth-child(1) .item{background-color: lightgreen;
}
.swiper-container swiper-item:nth-child(2) .item{background-color: lightblue;
}
.swiper-container swiper-item:nth-child(3) .item{background-color: lightpink;
}
swiper 组件的常用属性
实现文本长按选中复制效果
wxml
<!-- 实现文本长按选中复制效果 -->
<view>手机号支持长按选中复制效果<text user-select>110110110110</text>
</view>
渲染 HTML 标签
wxml
<rich-text nodes="<h1 style='color:red;'>标题</h1>"></rich-text>
按钮组件的使用效果
<!-- 按钮组件的基本使用 -->
<!-- 通过 type 属性指定按钮颜色类型 -->
<button>普通按钮</button>
<button type="primary">主色调按钮</button>
<button type="warn">警告按钮</button>
<!-- size="mini" 小尺寸按钮 -->
<button size="mini">普通按钮</button>
<button type="primary" size="mini">主色调按钮</button>
<button type="warn" size="mini">警告按钮</button>
<!-- plain 镂空按钮 -->
<button size="mini" plain>普通按钮</button>
<button type="primary" size="mini" plain>主色调按钮</button>
<button type="warn" size="mini" plain>警告按钮</button>
图片组件的使用效果
wxml
<image></image>
<image src="/image/微信开发者工具.png" mode="heightFix"></image>
wxss
image {border: 1px solid red;
}
image 组件 mode 属性的常用选项
Mustache 语法
动态绑定内容(定义变量,渲染变量)
js
/*** 页面的初始数据*/data: {info:'hello wx'},
wxml
<view>{{info}}</view>
动态绑定属性(将属性定义为变量并使用)
js
/*** 页面的初始数据*/data: {imgSrc:"/image/微信开发者工具.png"},
wxml
<image src="{{imgSrc}}"></image>
使用三元运算
js
/*** 页面的初始数据*/data: {//生成 10 以内的随机数randomNum:Math.random()*10 },
wxml
<view>{{randomNum>5?'随机数字大于5':'随机数字小于5'}}</view>
算术运算
js
/*** 页面的初始数据*/data: {//在 0,1 之间生成带两位小数的随机数randomNum:Math.random().toFixed(2)},
wxml
<view>{{randomNum*100}}</view>
事件绑定
触摸事件绑定
为按钮绑定触摸事件,当点击按钮(触发事件)后,逻辑层会得到 event 对象(可简写为 e ),包含该事件的详细属性,打印该 event 对象
event 对象的相关属性
js
/*** 按钮的事件处理函数*/tapHandler(e){console.log(e);},
wxml
<button type="primary" bind:tap="tapHandler">按钮</button>
触摸事件发生改变 data 中数据的值
为按钮绑定触摸事件,当点击按钮 (触发事件)后,data 中定义的数据 count 会加 1
js
/*** 页面的初始数据*/data: {count:0},/*** +1 事件处理函数*/addTapHandler(){this.setData({count:this.data.count+1})},
wxml
<button type="primary" bind:tap="addTapHandler">+1</button>
为事件处理函数传参
为按钮绑定触摸事件,当点击按钮 (触发事件)后,data 中定义的数据 count 会加 info ,info 是传给 事件处理函数的参数
js
/*** 页面的初始数据*/data: {count:0},/*** +2 事件处理函数*/addTapHandler(e){this.setData({//通过 e.target.dataset 获取传给事件处理函数的参数count:this.data.count+e.target.dataset.info})},
wxml
<!-- 通过 data- 传参-->
<!-- data-info="{{2}} 表示参数名称为 info ,值为整数 2 -->
<!-- data-info="2" 表示值为字符 2 -->
<button type="primary" bind:tap="addTapHandler" data-info="{{2}}">+2</button>
输入事件绑定
为输入框绑定输入事件,向输入框中输入数据时,触发事件,逻辑层打印输入框中最新的信息
js
/*** 输入事件处理函数* */ inputHandler(e){// e.detail.value 中包含了发生变化后,文本框中最新的值console.log(e.detail.value)},
wxml
<!-- 通过 bindinput 绑定输入事件 -->
<input bindinput="inputHandler"></input>
实现文本框和 data 之间的数据同步
为输入框绑定输入事件,向输入框中输入数据时,将数据同步给 data 中定义的变量
js
/*** 页面的初始数据*/data: {msg:"你好!"},/*** 输入事件处理函数* */ inputHandler(e){this.setData({msg:e.detail.value})},
wxml
<!-- 通过 bindinput 绑定输入事件 -->
<!-- 通过 value 设置输入框的初始值 -->
<input value="{{msg}}" bindinput="inputHandler"></input>
wxss
input{border: 1px solid red;padding: 5px;margin: 5px;border-radius: 3px;
}
条件渲染(根据一定条件进行渲染)
男,女,保密只能渲染一个,根据 data 中定义的变量来判断渲染哪个数据
js
/*** 页面的初始数据*/data: {type:1},
wxml
<!-- === 表示数据,类型均相等 -->
<!-- wx:if wx:elif wx:else 来进行条件渲染-->
<view wx:if="{{type===1}}">男</view>
<view wx:elif="{{type===2}}">女</view>
<view wx:else>保密</view>
使用 block 包装组件(单纯的容器)
对外层的容器或组件进行条件判断,如果为 true 则所有子元素内容都渲染,如果为 false 则所有子元素内容都不渲染
wxml
<!-- block 不是一个组件,它只是一个包裹性质的容器,不会在页面中做任何的渲染 -->
<block wx:if="{{false}}"><view>1</view><view>2</view>
</block>
使用 hidden 进行条件渲染
hidden 表示隐藏,值为 true 隐藏,为 false 显示
wxml
<!-- hidden 表示隐藏,值为 true 隐藏,为 false 显示 -->
<view hidden="{{true}}}">hello</view>
列表渲染
获取列表中的数据,循环渲染重复的组件结构
js
/*** 页面的初始数据*/data: {array:['张三','李四','王五']},
wxml
<!-- 通过 wx:for 指定数组,循环渲染重复的组件结构 -->
<!-- 当前遍历到的元素的索引用 index 获取,元素用 item 获取 -->
<!-- 通过 wx:key 为渲染出来的列表项指定唯一的key值,从而提高渲染效率 -->
<view wx:for="{{array}}" wx:key="{{index}}">索引是:{{index}},元素是{{item}}
</view>
导入外联样式表
通过 @import 导入外联样式表
@import "/common/common.wxss";
window 节点常用的配置项
以下配置项在每个页面单独的 .json 配置文件中都可使用,为页面进行特殊配置
设置导航栏的背景色
在全局配置文件 app.json 中找到 window - navigationBarBackgroundColor ,进行修改
app.json
"window": {"navigationBarTextStyle": "black","navigationBarTitleText": "Weixin",//设置导航栏的背景色"navigationBarBackgroundColor": "#2b4b6b"},
设置导航栏的标题内容
在全局配置文件 app.json 中找到 window - navigationBarTitleText,进行修改
app.json
"window": {"navigationBarTextStyle": "black",//设置导航栏的标题内容"navigationBarTitleText": "雨林小程序","navigationBarBackgroundColor": "#2b4b6b"},
设置导航栏的标题颜色
在全局配置文件 app.json 中找到 window - navigationBarTextStyle,进行修改,注意目前只支持黑色 black 和白色 white
app.json
"window": {//设置导航栏的标题颜色"navigationBarTextStyle": "white","navigationBarTitleText": "雨林小程序","navigationBarBackgroundColor": "#2b4b6b"},
开启下拉刷新效果
开启该功能我们可以通过下拉页面的方式,刷新(重新获取)小程序中的内容。通过在全局配置文件 app.json 的 window 部分添加 "enablePullDownRefresh" 属性开启
app.json
"window": {"navigationBarTextStyle": "white","navigationBarTitleText": "雨林小程序","navigationBarBackgroundColor": "#2b4b6b",//设置导航栏的下拉刷新效果"enablePullDownRefresh": true},
设置下拉刷新时窗口的背景色
通过在全局配置文件 app.json 的 window 部分添加 "backgroundColor" 属性开启
app.json
"window": {"navigationBarTextStyle": "white","navigationBarTitleText": "雨林小程序","navigationBarBackgroundColor": "#2b4b6b","enablePullDownRefresh": true,//设置导航栏下拉刷新时的背景色"backgroundColor": "#efefef"},
设置下拉刷新时 loading(加载) 的样式
通过在全局配置文件 app.json 的 window 部分添加 "backgroundTextStyle" 属性开启,注意目前仅支持 dark 和 light
app.json
"window": {"navigationBarTextStyle": "white","navigationBarTitleText": "雨林小程序","navigationBarBackgroundColor": "#2b4b6b","enablePullDownRefresh": true,"backgroundColor": "#efefef",//设置下拉刷新时加载的样式"backgroundTextStyle": "dark"},
设置上拉触底的距离(一般默认即可)
设置当用户在进行上拉操作获取数据时,在拉取多少距离后开始自动加载后面的数据,默认是 50 px ,一般没有特殊要求不建议修改,在全局配置文件 app.json 的 window 部分添加 "onReachBottomDistance" 属性开启
app.json
"window": {"navigationBarTextStyle": "white","navigationBarTitleText": "雨林小程序","navigationBarBackgroundColor": "#2b4b6b","enablePullDownRefresh": true,"backgroundColor": "#efefef","backgroundTextStyle": "dark",/*设置上拉触底的距离*/"onReachBottomDistance": 100},
下拉刷新
监听用户下拉动作
通过页面相关事件处理函数( onPullDownRefresh() )--监听用户下拉动作
点击 +1 按钮增加 count 的值
下拉刷新,将 count 的值改为 0
wxml
<text>首页</text>
<view>count: {{count}}</view>
<button bind:tap="addCount" type="primary">+1</button>
js
/*** 页面的初始数据*/data: {count:0},/*** 增加 count 的值*/addCount(){this.setData({count:this.data.count+1})},/*** 页面相关事件处理函数--监听用户下拉动作*/onPullDownRefresh() {//当用户下拉时,将 count 的值重置为 0 this.setData({count:0})},
停止下拉刷新效果(刷新完成,自动停止)
上面我们制作的下拉刷新效果存在刷新窗口一直存在的问题,我们需要在刷新的处理函数执行好后,停止刷新效果。
通过 wx.stopPullDownRefresh() 方法停止刷新效果
js
/*** 页面相关事件处理函数--监听用户下拉动作*/onPullDownRefresh() {//当用户下拉时,将 count 的值重置为 0 this.setData({count:0})//停止下拉刷新wx.stopPullDownRefresh()},
上拉触底
上拉触底是移动端的专有名词,通过手指在屏幕上的上拉滑动操作,从而加载更多数据的行为
上拉触底案例
上拉触底-刷新数据效果
案例步骤:
1.定义获取随机颜色的方法(主要知识:发送网络请求,接收和利用响应数据)
2.在页面加载时获取初始数据
3.渲染 UI 结构并美化页面效果
4.在上拉触底时调用获取随机颜色的方法、
5.添加 loading 提示效果(在获取数据时提示用户等待)
6.对上拉触底进行节流处理(用户可能频繁上下滑动,多次经过上拉触底的临界点,频繁发送请求,对于这个情况要加以限制)
wxml
<text>首页</text>
<!-- style:内联地定义元素的样式,在 css 中获取不到 colorList 中的数据内容-->
<view class="colorPiece" wx:for="{{colorList}}" wx:key="index" style="background-color: rgb({{item}});">
{{item}}</view>
wxss
.colorPiece{/* 设置边框 */border: 2rpx solid #efefef;/* 设置圆角 */border-radius: 10rpx;/* 设置行高 */line-height: 200rpx;/* 设置外边距 */margin: 20rpx;/* 设置文本位置(文本居中) */text-align: center;/* 设置文本阴影 */text-shadow: 0rpx 0rpx 5rpx #fff;/* 设置盒子阴影(view 模块) */box-shadow: 1rpx 1rpx 6rpx #aaa;
}
js
/*** 页面的初始数据*/data: {//存储随机颜色数据的列表colorList:[],//为了避免多次触碰上拉触底的临界值,导致一瞬间发送多条网络请求这个问题//定义一个节流阀,false 表示当前没有发送请求获取数据,true 表示当前正在发送请求获取数据isLoading:false},/*** 发起网络请求,从服务器获取颜色数据*/getColors(){//发送网络请求,将 isLoading 设为 true 进行标识this.setData({isLoading:true})this.data.isLoading//发送请求向服务器获取数据需要用户等待一段时间,显示等待标志wx.showLoading({title: '客官请稍等...',})wx.request({//服务器的 URLurl: 'https://applet-base-api-t.itheima.net/api/color',//https 请求的类型method:'GET',//成功接收到响应的处理逻辑//res 中是所有的响应内容success:(res)=>{this.setData({//res.data 表示获取响应内容,res.data.data 表示获取响应内容中 data 变量里的内容//... 是展开语法只能用于数组或可迭代对象,获取数组中的所有数据colorList:[...this.data.colorList,...res.data.data]})},//当请求完成以后将等待标志关闭complete:()=>{wx.hideLoading()//请求完成,设置 isLoading 标识为 falsethis.setData({isLoading:false})}})},/*** 生命周期函数--监听页面加载*/onLoad(options) {//在页面一加载就去获取颜色数据this.getColors()},/*** 页面上拉触底事件的处理函数*/onReachBottom() {//在调用 getColors() 方法发送网络请求前先判断,当前是否已经发送了网络请求if(this.data.isLoading) returnthis.getColors()},
tabBar 配置页面跳转标签
tabBar 页面跳转标签的组成部分
tabBar 节点的配置项(标红的配置必须有)
配置页面跳转标签 tab
每个 tab 标签的配置选项(标红的配置必须有)
在全局配置文件 app.json 中配置 tabBar
app.json
"tabBar": {"list": [{"pagePath": "pages/home/home","text": "首页","iconPath": "/image/home.png","selectedIconPath": "/image/home-active.png"},{"pagePath": "pages/userMessage/userMessage","text": "我的","iconPath": "/image/useMessage.png","selectedIconPath": "/image/useMessage-active.png"},{"pagePath": "pages/contact/contact","text": "联系我们","iconPath": "/image/contact.png","selectedIconPath": "/image/contact-active.png"} ]},
网络数据请求
微信小程序要先在管理后台配置服务器域名,才能给该域名服务器发送请求
1.首先登录微信小程序管理后台,在开发处找到开发管理
2.在开发设置中向下拉
3.找到服务器域名,点击修改,配置服务器域名
4.将域名输入到 request 合法域名即可
发起 GET 请求
wxml
<button bind:tap="getRequest">发起 GET 请求</button>
js
/*** 发送 GET 请求*/getRequest(){wx.request({url: 'https://applet-base-api-t.itheima.net/api/get',// 请求的地址,必须基于 https 协议method:'GET', // 请求的方式data:{ // 请求发送给服务器的数据name:'zs',age:22},success:(rep)=>{ // 请求成功后得到的响应结果console.log(rep.data)}})},
将类型 GET 改成 POST 即可发送 POST 请求
关于 GET 和 POST 类型的区别推荐看认识HTTP请求
页面加载时便请求数据
有很多情况下,我们需要在页面刚加载时,自动请求一些初始化的数据。此时需要在页面的 ,.js 文件的 onLoad 事件中调用获取数据的函数
wxml
<button>发起 GET 请求</button>
js
/*** 发送 GET 请求*/getRequest(){wx.request({url: 'https://applet-base-api-t.itheima.net/api/get',// 请求的地址,必须基于 https 协议method:'GET', // 请求的方式data:{ // 请求发送给服务器的数据name:'zs',age:22},success:(rep)=>{ // 请求成功后得到的响应结果console.log(rep.data)}})},/*** 生命周期函数--监听页面加载*/onLoad(options) {this.getRequest()},
滚动选择器
普通选择器
wxml
<view class="section"><view class="section__title">普通选择器</view><picker bindchange="bindPickerChange" value="{{index}}" range="{{array}}"><view class="picker">当前选择:{{array[index]}}</view></picker>
</view>
js
data: {array: ['', '中国', '巴西', '日本'],objectArray: [{id: 0,name: '美国'},{id: 1,name: '中国'},{id: 2,name: '巴西'},{id: 3,name: '日本'}],index: 0,},
页面导航
导航到 tabBar 页面
点击 导航到 ”我的“页面
跳转到 ”我的“ 页面
wxml
<text>首页</text>
<!-- url 是要跳转的页面地址,必须以 / 开头 -->
<!-- open-type 表示跳转的方式,必须为 switchTab -->
<navigator url="/pages/userMessage/userMessage" open-type="switchTab">导航到 ”我的“页面</navigator>
导航到非 tabBar 页面
点击 导航到 ”练习“页面
跳转到 ”练习“ 页面
wxml
<text>首页</text>
<!-- url 是要跳转的页面地址,必须以 / 开头 -->
<!-- open-type 表示跳转的方式,为 navigate ,也可以直接不写该属性 -->
<navigator url="/pages/exercise/exercise" open-type="navigate">导航到 ”练习“页面</navigator>
导航到上一页(后退导航)
从首页导航到练习页,在练习页点击”后退到上一页“
返回到首页
wxml
<text>练习</text>
<!-- open-type 为 navigateBack 表示后退导航 -->
<!-- delta 的值是数字,表示后退的层级,默认为 1 -->
<navigator open-type="navigateBack" delta="1">后退到上一页</navigator>
页面导航 - 编程式导航
导航到 tabBar 页面
wx.switchTab()方法的参数
点击按钮
跳转到”我的“页面
wxml
<text>首页</text>
<button bind:tap="gotoMy">跳转到”我的“页面</button>
js
/*** 跳转到”我的“页面* 使用 wx.switchTab() 方法可以指定跳转到 tabBar 页面*/gotoMy(){wx.switchTab({url: '/pages/userMessage/userMessage',})},
导航到非 tabBar 页面
wx.navigateTo() 方法的相关参数
点击按钮
跳转到练习页面
wxml
<text>首页</text>
<button bind:tap="gotoExercise">跳转到”练习“页面</button>
js
/*** 跳转到练习页面* 使用 wx.navigateTo() 方法可以导航到非 tabBar 页面*/gotoExercise(){wx.navigateTo({url: '/pages/exercise/exercise',})},
后退导航
wx.navigateBack() 方法相关的参数
从首页跳转到练习页,然后在练习页点击后退到上一页
成功后退回首页
wxml
<text>练习</text>
<button bind:tap="gotoBack">后退到上一页</button>
js
/*** 后退到上一页* 使用 wx.navigateBack() 方法可以导航到上一页*/gotoBack(){wx.navigateBack({delta:1})},
页面导航 - 导航传参
声明式导航传参
点击跳转到”练习“页面
跳转到练习页面后在左下角的位置能够查看传递的页面参数
wxml
<text>首页</text>
<!-- 跳转到”练习“页面时携带参数 -->
<navigator url="/pages/exercise/exercise?name=zhsangsan&age=20">跳转到”练习“页面</navigator>
编程式导航传参
点击跳转到”练习“页面
跳转到练习页面后在左下角的位置能够查看传递的页面参数
wxml
<text>首页</text>
<button bind:tap="gotoExercise">跳转到”练习“页面</button>
js
/*** 跳转到练习页面* 使用 wx.navigateTo() 方法可以导航到非 tabBar 页面*/gotoExercise(){wx.navigateTo({url: '/pages/exercise/exercise?name=zhangsan&age=20',})},
接收导航参数
点击跳转到”练习“页面,向练习页面传了参数
将传给练习页面的参数内容放到练习页面 js 文件的 data 中,方便使用
练习页面的 js 文件
/*** 页面的初始数据*/data: {name:{},age:{}},/*** 生命周期函数--监听页面加载*/onLoad(options) {// options 对象中保存了传递给页面的参数,可以从中获取,赋值给 data 中的变量,方便在其他地方使用this.setData({name:options.name,age:options.age})},
生命周期函数
应用生命周期函数
页面生命周期函数
WXS 脚本
js 文件中的函数不能在 wxml 文件中使用,我们通过在 wxml 中内嵌 wxs 脚本,可以在 wxml 中使用 wxs 脚本定义的函数(方法),帮助渲染 UI 结构
内嵌 wxs 脚本
定义一个 wxs 脚本,将小写数据全变为大写再进行渲染
wxml
<text>首页</text>
<view>{{userName}}</view>
<view>{{upper.toUpper(userName)}}</view><!-- 每个 wxs 标签必须提供 module 属性 作为当前 wxs 的模块名称 -->
<wxs module="upper">
//通过 module.exports 向外共享成员
// toUpper=function(str) 表示向外共享的成员 toUpper 是一个参数为 str 的 函数module.exports.toUpper=function(str){return str.toUpperCase()}
</wxs>
js
/*** 页面的初始数据*/data: {userName:"zhangsan"},
外联 wxs 脚本
定义一个 .wxs 文件,在该文件中定义和共享 toLower 函数,将大写数据全变为小写再进行渲染
wxml
<text>首页</text>
<view>{{userName}}</view>
<view>{{lower.toLower(userName)}}
</view><!-- 这里要写 .wxs 文件的相对路径 ../ 表示上级目录 -->
<wxs src="../../utils/tools.wxs" module="lower"></wxs>
wxs
//定义了一个将字符串变成小写的方法
function toLower(str){return str.toLowerCase()
}
//向外共享 toLower 方法
module.exports={toLower:toLower
}
通过 wxs 脚本修改电话格式
没有使用 wxs 脚本的格式
使用了 wxs 脚本的格式
消息提示框
wx.showToast 是一种轻量级的反馈,常用于展示操作结果或者给用户一些简短的提示信息。
使用 wx.showToast
时,你可以设置不同的参数来定制 Toast 的外观和行为。以下是一些常用的参数:
title
:提示的内容icon
:显示的图标,有效值包括 "success", "loading", "none"image
:自定义图标的本地文件路径,当设置了image
时,icon
参数会被忽略duration
:提示的延迟时间,单位毫秒,默认 1500mask
:是否显示透明蒙层,防止触摸穿透,默认 falsesuccess
:接口调用成功的回调函数fail
:接口调用失败的回调函数complete
:接口调用结束的回调函数(调用成功、失败都会执行)
js
wx.showToast({ title: '操作成功', icon: 'success', duration: 2000
});
wxml
<text>{{tools.splitPhone(item.phone)}}</text>
<wxs src="../../utils/tools.wxs" module="tools"/>
wxs
function splitPhone(phone){if(phone.length!=11){return phone}//将电话号码字符串拆分成一个字符数组var phoneArr=phone.split('')//数组的 splice 方法用于在数组中添加或删除元素,第一个参数:要改变的位置,第二个参数:要删除的元素个数,第三个参数:要添加的元素phoneArr.splice(3,0,'-')phoneArr.splice(8,0,'-')//将数组的所有元素连接到一个字符串中,参数表示分隔符,会插入到两个元素之间return phoneArr.join('')
}//向外共享方法
module.exports={splitPhone:splitPhone
}
自定义组件
创建组件文件
点击新建文件夹,创建一个 components 文件,用来放置所有的组件文件,在 components 文件下右键新建一个 test 文件作为组件文件,右键 test 文件点击新建 Component 创建组件文件应该有的各种.js .json .wxml .wxss 文件
局部引入组件
局部引入组件后,只有引入组件的页面可以使用组件
在页面的 .json 配置文件的 "usingComponents" 配置项中输入组件的名称(自定义)和组件的路径,配置好以后便可以在当前页面的 .wxml 文件中使用
wxml
<text>首页</text>
<view></view>
<my-test1></my-test1>
.json
{"usingComponents": {"my-test1":"/components/test/test"}
}
全局引入组件
全局引入组件后,所有的页面都可以使用组件
在全局的 app.json 配置文件的 "usingComponents" 配置项中输入组件的名称(自定义)和组件的路径,配置好以后便可以在所有页面的 .wxml 文件中使用
wxml
<text>首页</text>
<view></view>
<my-test1></my-test1>
app.json
"usingComponents": {"my-test1":"/components/test/test"},
自定义组件的样式隔离选项
默认情况下组件的样式隔离能够防止组件内外相互干扰的问题(页面的样式配置无法影响组件,组件的样式配置也无法影响页面),但有时我们也希望在外界能够影响组件内部的样式,或者组件内部的样式能够影响外界,我们就可以通过 styleIsolation 修改组件的样式隔离选项
styleIsolation 的相关选项
在组件的 .js 文件中添加如下配置:
options:{styleIsolation:"isolated"}
或在组件的 .json 文件中添加如下配置:
"styleIsolation": "isolated"
自定义主键的数据和方法定义
定义一个组件,使用该组件就能直接在页面中得到一个 count 数据的展示和 +1 按钮,点击 +1 按钮,count 数据增加,弹出提示
页面的 .wxml 文件
可以看到只是简单的使用了自定义的 my-test1 组件
<!--pages/home/home.wxml-->
<text>首页</text>
<view></view>
<my-test1></my-test1>
组件的 .wxml 文件
<view>count:{{count}}</view>
<button bind:tap="addCount" type="primary">+1</button>
组件的 .js 文件
/*** 组件的初始数据*/data: {count:0},/*** 组件的方法列表*/methods: {addCount(){this.setData({count:this.data.count+1})this._showHint()},//自定义方法推荐以 _ 开头,方便区别事件处理函数和自定义方法的区别_showHint(){wx.showToast({title: 'count:'+this.data.count,icon:"none"})}}
自定义组件传参以及参数获取
设置参数 max 为 6,在 count 为 6 时点击 +1 count 值不再改变
在组件的 .js 文件中通过 properties 选项来创建属性,用于接收外界传给组件的参数。
在使用自定义组件时向组件传入一个 max 参数,限制 count 的最大值
页面的 .wxml 文件
<text>首页</text>
<view></view>
<!-- 使用自定义组件 my-test1 传入 max 参数,表示 count 的最大值 -->
<my-test1 max="6"></my-test1>
组件的 .wxml 文件
<view>count:{{count}}</view>
<button bind:tap="addCount" type="primary">+1</button>
组件的 .js 文件
Component({/*** 组件的属性列表*///通过 properties 选项来创建属性,用于接收外界传给组件的参数properties: {//完整定义属性的方式,type 表示类型,value 表示默认值max:{type:Number,value:10},//简化定义属性的方式,age 是属性名,Number 是属性类型max:Number},/*** 组件的初始数据*/data: {count:0},/*** 组件的方法列表*/methods: {addCount(){//判断 count 值是否已经达到最大值(用户传入的参数)if(this.data.count>=this.properties.max){return}this.setData({count:this.data.count+1})this._showHint()},//自定义方法推荐以 _ 开头,方便区别事件处理函数和自定义方法的区别_showHint(){wx.showToast({title: 'count:'+this.data.count,icon:"none"})}}
})
使用数据监听器
通过在 .js 文件中使用 observers 选项来使用数据监听器,监听哪些数据项发生变化,并获得变化后的数据,进行相应的处理
如下视频,监听变量一 n1 和变量二 n2 的值,监听 n1 和 n2 值发生改变后,计算 n1 + n2 的结果,赋值给 sum
数据监听器
页面的 .wxml 文件
<text>首页</text>
<view></view>
<!-- 使用自定义组件 my-test1 -->
<my-test1></my-test1>
组件的 .wxml 文件
<view>{{n1}}+{{n2}}={{sum}}</view>
<button type="primary" bind:tap="addN1">变量一 + 1</button>
<button type="primary" bind:tap="addN2">变量二 + 1</button>
组件的 .js 文件
Component({/*** 组件的属性列表*///通过 properties 选项来创建属性,用于接收外界传给组件的参数properties: {},/*** 组件的初始数据*/data: {n1:0,n2:0,sum:0},/*** 组件的方法列表*/methods: {//增加 n1 数据addN1(){this.setData({n1:this.data.n1+1})},//增加 n2 数据addN2(){this.setData({n2:this.data.n2+1})}},//数据监听器observers:{//监听 n1 和 n2 数据的变化'n1,n2':function(n1,n2){//当 n1 和 n2 的数据发生变化后,修改 sum 的数据this.setData({sum:this.data.n1+this.data.n2})}}
})
监听对象中指定属性的变化
如下代码,监听了 rgb 对象中 r,g,b 属性的变化,并进行相应的操作
监听对象中所有属性的变化
去一个个监听对象中的属性比较麻烦,可以通过 .** 监听对象中的所有属性,属性改变后的值放到 obj 对象中,通过参数对象 . 属性名得到改变的值
纯数据字段
如果自定义组件的 data 中某些字段不用于界面渲染,也不传递给其他组件,这些字段就适合被定义为纯数据字段,纯数据字段有助于提高页面更新的性能
在组件 .js 文件与 data 同级写一个 option 选项,option 选项的 pureDataPattern 属性可以通过正则表达式指定纯数据字段的格式,data 中满足这个格式的字段就是纯数据字段
组件的生命周期函数
自定义组件有如下生命周期函数
通过在组件的 .js 文件中与 data 同级别的 lifetimes 选项中使用
组件的 .js 文件
lifetimes:{created(){console.log('组件创建')},attached(){console.log('组件进入页面,但还没渲染')},ready(){console.log('组件在页面上渲染完毕')}},
组件所在页面的生命周期
有时候自定义组件需要监听所在页面的状态,当页面状态发生变化时组件需要进行一定的操作,比如当页面刚被展示时,组件的颜色便随机刷新。
通过在组件的 .js 文件与 data 平级的 pageLifetimes 中使用
组件监听所在页面的生命周期函数有以下三个:
/*** 组件所在页面的生命周期函数*/pageLifetimes:{//在页面被展示时,组件执行的操作show:function(){},//在页面被隐藏时,组件执行的操作hide:function(){},//在页面的尺寸发生变化时,组件执行的操作resize:function(size){}},
组件所在页面的生命周期案例
现在我们有一个组件是一个色块,我们这个组件需要监听组件所在的页面是否被展示,当页面被展示时,随机更改组件的颜色
组件的 .wxml 文件
<view style="background-color: rgb({{color.r}}, {{color.g}}, {{color.b}});" class="colorLump">({{color.r}},{{color.g}},{{color.b}})</view>
组件的 .wxss 文件
.colorLump{color: white;line-height: 200rpx;text-align: center;
}
组件的 .js 文件
/*** 组件所在页面的生命周期函数*/pageLifetimes:{//在页面被展示时,组件执行的操作show:function(){//在页面展示时改变 data 中的 color 对象this.chageColor()},//在页面被隐藏时,组件执行的操作hide:function(){},//在页面的尺寸发生变化时,组件执行的操作resize:function(size){}},/*** 组件的初始数据*/data: {// color 对象的 r,g,b 属性表示色块的颜色color:{r:0,g:0,b:0}},/*** 组件的方法列表*/methods: {chageColor(){//在页面展示时改变 data 中的 color 对象this.setData({color:{r:Math.floor((Math.random()*256)),g:Math.floor((Math.random()*256)),b:Math.floor((Math.random()*256))}})}},
单个插槽
插槽的意思就是,在组件中的某些地方,并不知道使用者要放的内容是什么,所以使用一个 slot 标签来进行占位,让用户可以随意在该处放置内容
在小程序中,默认每个自定义组件只允许使用一个 <slot> 进行占位,这种个数上的限制叫做单个插槽
组件的 .wxml 文件
<view><view>这是组件内部</view><!-- 对于不确定的内容,可以用 slot 标签进行占位,具体内容由组件的使用者来确定 --><slot></slot>
</view>
页面的 .wxml 文件
<text>首页</text>
<view></view>
<!-- 使用自定义组件 test -->
<my-test><view>用户自定义占位符处的内容</view>
</my-test>
多个插槽
默认情况下我们在组件中只能定义一个插槽,但如果我们需要定义多个插槽,也可以通过在组件的 .js 文件中配置 options 选项的属性 multipleSlots 为 true
在定义多个插槽时,要通过 name 属性来进行区分,在页面中使用插槽时,通过 slot 属性来指定该内容放置的插槽
组件的 .js
options:{//开启多个插槽multipleSlots:true},
组件的 .wxml 文件
<view><!-- 对于不确定的内容,可以用 slot 标签进行占位,具体内容由组件的使用者来确定 --><!-- 定义多个插槽时,使用 name 来进行区分 --><!-- 定义 name 为 before 的插槽 --><slot name="before"></slot><view>这是组件内部</view><!-- 定义 name 为 after 的插槽 --><slot name="after"></slot>
</view>
页面的 .wxml 文件
<text>首页</text>
<view></view>
<!-- 使用自定义组件 test -->
<my-test>
<!-- 在向插槽中放置内容时,使用 slot 属性指定该内容要放置的插槽 name --><view slot="before">before 占位符处的内容</view><view slot="after">after 占位符处的内容</view>
</my-test>
父子组件之间的通信 - 父向子传值
通过属性绑定来实现父向子传值,但只能传输数据,不能传输方法
页面为父组件,我们自定义的组件 my-test 为子组件,通过向子组件传参的方式,将页面 data 中定义的变量的值传给子组件
组件的 .js 文件
//通过 properties 选项来创建属性,用于接收外界传给组件的参数properties: {userName:String},
组件的 .wxml 文件
<view><view>这是组件内部</view><view>组件内部得到 userName 为 {{userName}}</view>
</view>
页面的 .wxml 文件
<text>首页</text>
<view></view>
<!-- 使用自定义组件 test -->
<!-- 向自定义组件中传一个参数 userName -->
<view>页面中 userName 定义为 {{userName}}
</view>
<my-test userName="{{userName}}"></my-test>
父子组件之间的通信 - 子向父传值
同步数据
通过事件绑定实现子向父传值,可以传递任何类型的数据
核心就是通过自定义事件绑定,使在子组件中可以调用父组件中自定义事件绑定的事件处理函数,也可以为该事件处理函数传递参数,就可以利用传递函数参数来向父组件传递数据
下面通过一个同步父子组件数据的例子来介绍过程,我们要在改变子组件中 count 数据时同步修改父组件中的 count 数据
首先在父组件中使用子组件时,为子组件绑定一个自定义事件
<text>首页</text>
<view></view>
<view>页面中的 count 值:{{count}}</view>
<!-- 使用自定义组件 my-test -->
<!-- 通过 bind:事件名称 为子组件绑定一个自定义事件 -->
<my-test bind:sync="syncCount"></my-test>
在子组件的 .js 文件中,在子组件的 count 值增加以后调用自定义事件 sync ,来执行父组件中定义的事件处理函数 syncCount ,并且为该事件处理函数传参
/*** 组件的初始数据*/data: {count:0},/*** 组件的方法列表*/methods: {addCount(){this.setData({count:this.data.count+1})//通过 this.triggerEvent('自定义事件名称',{参数对象}) 的方式调用父组件中绑定自定义事件的函数并且给函数传参this.triggerEvent('sync',{value:this.data.count})}},
在父组件的 .js 文件中定义事件处理函数 syncCount ,在子组件调用时,用子组件传来的参数 value 值来更新 data 中的 count 值
/*** 页面的初始数据*/data: {count:0},/*** 自定义事件处理函数* 用于同步 count 值*///子组件传来的参数用 e 形参接收,在 e.detail 中syncCount(e){console.log(e)this.setData({count:e.detail.value})},
访问子组件的任意数据和方法
通过定义在主页中的按钮,可以修改组件中的 count 值
在父组件里调用 this.selectComponent(" id 或 class 选择器"),获取子组件的实例对象,从而直接访问子组件的任意数据和方法
主页的 .wxml 文件
<!-- 使用自定义组件 my-test -->
<my-test class="my-test"></my-test>
<button type="primary" bind:tap="addCount">count+1(位于主页)</button>
主页的 .js 文件
//增加子组件中的 count 值addCount(){//获取类名为 my-test 的子组件实例const child= this.selectComponent('.my-test')//通过子组件实例 child 可以调用子组件中的数据和方法child.setData({count:child.data.count+1})},
组件的 .wxml 代码
<view><view>组件中的 count 值:{{count}}</view>
</view>
组件间代码共享
通过 behaviors ,可以实现组件间代码共享,每个 behaviors 可以包含一组属性,数据,生命周期函数和方法。组件引用它时,它的属性,数据,生命周期函数和方法会被合并到组件中、
在 .js 文件中,调用 Behavior( Object object ) 方法即可创建一个共享的 behavior 实例对象,供所有的组件使用
behavior 中可用的节点(组件间可用共享的节点)
创建 behavior
创建一个 behaviors 文件夹,在文件夹下创建一个 .js 文件用于定义 behaviors
.js 文件
//通过在 .js 文件中调用 Behavior 方法来创建 behavior 对象,用于共享组件的通用代码
//通过 module.exports 将 behavior 共享出去
module.exports=Behavior({//公共数据data:{name:"zhangsan"},//公共属性properties:{},公共方法methods:{}
})
导入并使用 behavior
在组件中,使用 require() 方法导入需要的 behavior ,通过在组件的 .js 文件中通过 behaviors 选项挂载后即可访问 behavior 中的数据和方法
组件的 .js 文件
//导入需要的 behavior
const myBehavior=require("../../behaviors/my-behaviors")
Component({//将导入的 behavior 实例对象,挂载到 behaviors 数组中,即可生效behaviors:[myBehavior]
})
组件的 .wxml 文件
<view><view>myBehavior 中的 name 属性为{{name}}</view>
</view>
使用 Vant 组件
Vant 是一个轻量、可靠的移动端组件库,里面提供了许多小程序开发组件,能够提高小程序的开发效率
关于 Vant 组件库的安装和使用推荐看在微信小程序项目中安装和使用 Vant 组件库
定制 Vant 组件样式
通过设置 css 变量可以定制 Vant 组件的样式
我们可以在小程序的 app.wxss 文件下的 page 标签选择器中设置 css 变量,这样设置的 css 变量是作用于小程序所有页面的(因为小程序每个页面的根标签都是 page)
现在我们已经在 .wxml 中使用了两个按钮组件
<van-button type="default">默认按钮</van-button>
<van-button type="primary">主要按钮</van-button>
我们想自定制“主要按钮“的颜色,在 app.wxss 中设置 css 变量
/* page 是每个页面的根标签,在这个标签中设置 CSS 变量可以作用于所有的页面 */
page{--button-primary-background-color:#dc9f46;--button-primary-border-color: #dc9f46;
}
我们如何知道 Vant 组件有哪些 css 变量呢?在官网就能找到
在 Vant 组件的官网,我们选择定制主题,点击配置文件链接
就能看到所有 Vant 组件可定制的 CSS 变量(注意在 css 变量名前要加 -- )
小程序 api 的 promise 化
让基于回调函数的 api 进行 promise 化可以使代码可读性增强,避免回调地狱,代码复用性提高等好处,Promise 和 async/await 已经成为现代 JavaScript 开发中的标准做法
首先安装 miniprogram-api-promise 第三方 npm 包,实现 API Promise 化主要依赖于这个包
1.在微信开发者工具文件目录的空白处右键,点击在外部终端窗口中打开,在命令行窗口输入以下指令
npm i --s miniprogram-api-promise@1.0.4
2.构建 npm ,在右上角点击工具,选择构建 npm
在 miniprogram_npm 文件下我们可以看到,这个包已经安装好了
3.API Promise 化
在 app.js 文件中,与 App() 选项同级的位置输入如下代码
import{promisifyAll}from 'miniprogram-api-promise'
const wxp=wx.p={}
promisifyAll(wx,wxp)App({...})
调用 Promise 化后的异步 API
将发起网络请求获取数据的方法进行 Promise 化
.js 文件
通过回调函数的方法发生网络请求使用 wx.request() 方法,Promise 化后通过 wx.p.request 发送网络请求,并且在方法前和发起请求前用 async 和 await 修饰
async getInfo(){const res=await wx.p.request({method:'GET',url:'https://applet-base-api-t.itheima.net/api/get',data:{name:'zs',age:18}})console.log(res)},
全局数据共享
有一些数据可能小程序的很多组件和页面都需要用到,传递起来就很麻烦,所以可以用 mobx 相关的包来实现全局数据共享
mobx-miniprogram 用来创建 Store 实例对象( Store 实例对象用于存储全局的数据或方法)
mobx-miniprogram-bindings 用来将 Store 中存储的数据和方法,绑定到组件或页面中使用
安装 mobx 相关的包
1.在项目文件目录的空白处右键选择 “在外部终端窗口中打开” ,在命令行中输入以下命令,安装 mobx 相关的两个包
npm install --save mobx-miniprogram@4.13.2 mobx-miniprogram-bindings@1.2.1
2.构建 npm ,在右上角点击工具,选择构建 npm,在 miniprogram_npm 文件下找到我们刚才安装的两个 mobx 相关的包就说明构建成功
创建 Store 实例
全局的数据和方法要放到 Store 实例中
首先创建一个 store 文件夹,在文件夹中创建一个 store.js 文件
// 在这个 .js 文件中,专门创建 store 的实例对象
//导入创建 store 实例对象的包
//{...} 中是要在包中导出的方法
// observable 是创建 store 实例对象需要用到的方法
// action 用于修改 store 中的数据
import {observable,action} from 'mobx-miniprogram'
// 通过 observable 方法创建实例对象,通过 export 导出实例对象
// 外界需要的时候可以导入这个 store 实例,使用里面的数据和方法
export const store= observable({// 在 observable 方法中传入的参数对象中设置全局的属性和方法//数据字段num1:10,num2:18,//计算属性// get 表示这个计算属性是只读的,只能通过 sum 方法获取数据,不能设置数据get sum(){return this.num1+this.num2},//修改 store 中的数据updateNum1:action(function(step){this.num1+=step}),updateNum2:action(function(step){this.num2+=step})
})
将 store 中的成员绑定到页面中
页面的 .js 文件
// 从 mobx-miniprogram-bindings 包中获取 createStoreBindings 方法
import {createStoreBindings} from 'mobx-miniprogram-bindings'
//在相对路径为'../../store/store'的文件中导出 store 实例对象
import{store}from '../../store/store'
Page({/*** 生命周期函数--监听页面加载*/onLoad(options) {//在页面加载时绑定 store 实例对象到页面上//this.storeBindings 接收 createStoreBindings 方法的返回值,在后面用于释放绑定时所用的资源this.storeBindings=createStoreBindings(this,{//数据源store,//属性fields:['num1','num2','sum'],//方法actions:['updateNum1','updateNum2']})},/*** 生命周期函数--监听页面卸载*/onUnload() {//当关闭页面后,要释放绑定 store 实例对象所用的资源this.storeBindings.detroyStoreBindings()}
})
在页面上使用 store 中的成员
使用store中的成员
store 中的成员绑定到页面上以后,直接按照正常 data 中的数据和正常定义的方法使用即可
页面的 .wxml 文件
<text>首页</text>
<!-- num1,num2,sum 是 store 中的属性 -->
<view>{{num1}}+{{num2}}={{sum}}</view>
<van-button type="primary" bind:tap="changeNum" data-step="{{1}}">num1+1
</van-button>
<van-button type="danger" bind:tap="changeNum" data-step="{{-1}}">num1-1
</van-button>
页面的 .js 文件
changeNum(e){// updateNum1 是 store 中的方法this.updateNum1(e.target.dataset.step);},
将 store 中的成员绑定到组件中
组件的 .js 文件
//在 mobx-miniprogram-bindings 包中导入 storeBindingsBehavior 方法,用于映射 store 中的成员
import{storeBindingsBehavior} from 'mobx-miniprogram-bindings'
// 在相对路径'../../store/store'中导入 store 数据源
import{store} from '../../store/store'Component({//将 storeBindingsBehavior 方法放入 behaviors 数组中来实现自动绑定 store 中的成员behaviors:[storeBindingsBehavior],//设置 storeBindings 对象,指明要导入 store 中的哪些成员storeBindings:{//数据源store,//属性fields:{//前面是在组件中使用的名字,后面是 store 中的成员名字num1:'num1',num2:'num2',sum:'sum'},//方法actions:{updateNum1:'updateNum1',updateNum2:'updateNum2'}}
})
在组件中使用 store 中的成员
使用store中的成员
store 中的成员绑定到组件上以后,直接按照正常 data 中的数据和正常定义的方法使用即可
组件的 .wxml 文件
<view><view>{{num1}}+{{num2}}={{sum}}</view><van-button type="primary" bind:tap="changeNum" data-step="{{1}}">num1+1</van-button><van-button type="danger" bind:tap="changeNum"data-step="{{-1}}">num1-1</van-button>
</view>
组件的 .js 文件
Component({/*** 组件的方法列表*/methods: {changeNum(e){this.updateNum1(e.target.dataset.step)}}
})
对小程序进行分包
在开发小程序时由一个主包+多个分包组成
- 主包:一般只包含项目的启动页面或 TabBar 页面,以及所有分包都需要用到的公共资源
- 分包:只包含和当前分包有关的页面和私有资源
在小程序启动时会下载主包中的内容并启动主包内页面,而分包中的内容和页面在访问时才会下载,进行分包以后减少了主包中的数据内容可以优化小程序首次启动的下载时间
app.json 文件
“pages” 数组中放置的是主包中的页面,"subPackages" 数组中放置的是分包的页面
"subPackages" 数组对象的属性:
root:表示分包的根目录
name:表示分包的别名
pages:表示分包页面的路径
{"pages": [ "pages/home/home","pages/userMessage/userMessage","pages/contact/contact"],"subPackages": [{"root": "pkgA","name": "animal","pages": ["pages/cat/cat","pages/dog/dog"]},{"root": "pkgB","name": "fruits","pages": ["pages/apple/apple","pages/bananer/bananer"]}]
}
创建出的分包目录
独立分包
独立分包和普通分包的区别:独立分包不依赖主包即可运行,可以很大程度上提高分包页面的启动速度,一个小程序中可以有多个独立分包
设置方法:在普通分包中添加 “independent” 属性即可将其设置为独立分包
如下代码,将别名为 animal 的分包设置为独立分包,而别名为 fruits 的分包依然是普通分包
"subPackages": [{"root": "pkgA","name": "animal","pages": ["pages/cat/cat","pages/dog/dog"],"independent": true},{"root": "pkgB","name": "fruits","pages": ["pages/apple/apple","pages/bananer/bananer"]}]
配置分包的预下载
如果在进入某个页面后,有很大的概率需要加载某些分包,我们可以配置这些分包预下载。
预下载分包的行为,会在进入指定的页面时触发。在 app.json 中,使用 preloadRule 节点定义分包的预下载规则:
如下代码定义了在进入 contact 页面时自动下载分包 pkgA
根据日志可以看出在进入 contact 页面时成功预下载分包 pkgA
自定义 tabBar
官方文档https://developers.weixin.qq.com/miniprogram/dev/framework/ability/custom-tabbar.html
1.配置信息
在 app.json
中的 tabBar
项指定 custom
字段,同时其余 tabBar
相关配置也补充完整。比如 list 数组以及其中的配置都不能省略,因为如果用户版本较低无法显示自定义的 tabBar 就会用 list 数组中的设置进行显示。而且要通过 list 数组中的设置来知道哪些是 tabBar 页面
"tabBar": {"custom": true,"list": [{"pagePath": "pages/home/home","text": "首页","iconPath": "/image/home.png","selectedIconPath": "/image/home-active.png"},{"pagePath": "pages/userMessage/userMessage","text": "我的","iconPath": "/image/useMessage.png","selectedIconPath": "/image/useMessage-active.png"},{"pagePath": "pages/contact/contact","text": "联系我们","iconPath": "/image/contact.png","selectedIconPath": "/image/contact-active.png"} ]}
2.添加 tabBar 代码文件
在代码根目录下添加文件夹 custom-tab-bar ,在该文件夹下创建 index 组件,注意名称必须正确
3.根据 Vant 组件来自定义 tabBar
Vant 中的 Tabbar 标签栏组件官网介绍https://vant-ui.github.io/vant-weapp/#/tabbar
引入组件
在 app.json
或 index.json
中引入组件
"usingComponents": {"van-tabbar": "@vant/weapp/tabbar/index","van-tabbar-item": "@vant/weapp/tabbar-item/index"
}
基础用法
在 index 组件的 .wxml 中使用
<van-tabbar active="{{ active }}" bind:change="onChange"><van-tabbar-item icon="home-o">标签</van-tabbar-item><van-tabbar-item icon="search">标签</van-tabbar-item><van-tabbar-item icon="friends-o">标签</van-tabbar-item><van-tabbar-item icon="setting-o">标签</van-tabbar-item>
</van-tabbar>
由于需要 active 变量,和 onChange() 方法,需要在 index 组件的 .js 文件中定义
Component({/*** 组件的初始数据*/data: {active: 0},/*** 组件的方法列表*/methods: {onChange(event) {// event.detail 的值为当前选中项的索引this.setData({ active: event.detail });}}
})
可以看到页面上已经出现了 tabBar 效果
4.根据 list 数组中定义的属性内容来批量设置 tabBar 效果
在 index 组件的 .js 文件中的 data 节点下创建一个 list 数组,包含 tabBar 的相关属性设置
data: {"list": [{"pagePath": "pages/home/home","text": "首页","iconPath": "/image/home.png","selectedIconPath": "/image/home-active.png"},{"pagePath": "pages/userMessage/userMessage","text": "我的","iconPath": "/image/useMessage.png","selectedIconPath": "/image/useMessage-active.png","info":1},{"pagePath": "pages/contact/contact","text": "联系我们","iconPath": "/image/contact.png","selectedIconPath": "/image/contact-active.png"} ]}
在组件的 .wxml 文件中通过 van-tabbar-item 组件循环设置 tabBar 效果
<van-tabbar active="{{ active }}"
bind:change="onChange">
<van-tabbar-item wx:for="{{list}}" wx:key="index" info="{{item.info?item.info:''}}"><imageslot="icon"src="{{item.iconPath}}"mode="aspectFit"style="width: 30px; height: 18px;"/><imageslot="icon-active"src="{{item.selectedIconPath}}"mode="aspectFit"style="width: 30px; height: 18px;"/>{{item.text}}</van-tabbar-item>
</van-tabbar>
5.在自定义组件中使用 Vant 组件,需要覆盖 Vant 组件原来的样式
要在组件的 .js 文件中的 options 节点下设置 styleIsolation 属性,这样才能覆盖 Vant 组件原来的样式
Component({options: {styleIsolation: 'shared',}
});
6.实现 tabBar 页面的切换效果
核心: tabBar 部分绑定了一个事件处理函数 onChange(),当我们选择 tabBar 标签后通过event.detail 可以获取该标签的下标,根据该标签的下标可以在 list 数组中得到对应页面的路径,通过 wx.switchTab()方法进行页面跳转, active 属性表示该标签的下标,要对 active 属性进行设置
要注意 active 属性不能定义在 index 组件的 .js 文件中,会有 bug,要将其定义在 store 中,再将定义在 store 中的属性 active 和 改变 active 的方法 updateActive 绑定到组件中
store.js 文件
// 在这个 .js 文件中,专门创建 store 的实例对象
//导入创建 store 实例对象的包
//{...} 中是要在包中导出的方法
// observable 是创建 store 实例对象需要用到的方法
// action 用于修改 store 中的数据
import {observable,action} from 'mobx-miniprogram'
// 通过 observable 方法创建实例对象,通过 export 导出实例对象
// 外界需要的时候可以导入这个 store 实例,使用里面的数据和方法
export const store= observable({// 在 observable 方法中传入的参数对象中设置全局的属性和方法//数据字段active:0,//计算属性//方法//通过 updateActive 方法修改 active 中的数据updateActive:action(function(index){this.active=index})
})
组件的 .wxml 文件
<van-tabbar active="{{ active }}"
bind:change="onChange" active-color="#13A7A0">
<van-tabbar-item wx:for="{{list}}" wx:key="index" info="{{item.info?item.info:''}}"><imageslot="icon"src="{{item.iconPath}}"mode="aspectFit"style="width: 30px; height: 18px;"/><imageslot="icon-active"src="{{item.selectedIconPath}}"mode="aspectFit"style="width: 30px; height: 18px;"/>{{item.text}}</van-tabbar-item>
</van-tabbar>
组件的 .js 文件
//映射 store 中的全局数据到组件中
//在 mobx-miniprogram-bindings 包中导入 storeBindingsBehavior 方法,用于映射 store 中的成员
import{storeBindingsBehavior} from 'mobx-miniprogram-bindings'
// 在相对路径'../../store/store'中导入 store 数据源
import{store} from '../store/store'
Component({//将 storeBindingsBehavior 方法放入 behaviors 数组中来实现自动绑定 store 中的成员behaviors:[storeBindingsBehavior],//设置 storeBindings 对象,指明要导入 store 中的哪些成员storeBindings:{//数据源store,//属性fields:{//前面是在组件中使用的名字,后面是 store 中的成员名字active:'active'},//方法actions:{updateActive:'updateActive'}},options:{styleIsolation:'shared'},/*** 组件的属性列表*/properties: {},/*** 组件的初始数据*/data: {"list": [{"pagePath": "/pages/home/home","text": "首页","iconPath": "/image/home.png","selectedIconPath": "/image/home-active.png"},{"pagePath": "/pages/userMessage/userMessage","text": "我的","iconPath": "/image/useMessage.png","selectedIconPath": "/image/useMessage-active.png","info":1},{"pagePath": "/pages/contact/contact","text": "联系我们","iconPath": "/image/contact.png","selectedIconPath": "/image/contact-active.png"} ]},/*** 组件的方法列表*/methods: {onChange(event) {//设置 store 中的 active 值this.updateActive(event.detail)// event.detail 的值为当前选中项的索引//根据当前项的索引值就知道页面信息在 list 数组的哪个位置,从 list 数组中获取页面路径,通过 wx.switchTab() 进行跳转wx.switchTab({url: this.data.list[event.detail].pagePath})}}
})