微信小程序开发
一、小程序简介
与普通网页开发的区别
- 1、运行环境不同:微信环境
- 2、API不同:无法调用DOM和BOM,可以调用微信环境的API
- 3、开发模式不同:申请小程序开发账号,安装小程序开发工具,创建和配置小程序项目。
二、创建小程序账号
https://mp.weixin.qq.com
小程序ID
微信开发者工具
https://developers.weixin.qq.com/miniprogram/dev/devtools/stable.html


三、小程序项目结构




四、新建小程序页面
app.json -> pages 中新增页面的存放路径。小程序开发者工具即可帮我们自动创建对应的页面文件,如图:

修改项目首页







Swiper组件的使用
<!--pages/list/list.wxml-->
<swiper class="swiper-container"
indicator-dots 是否显示面板指示点
ndicator-color="white" 指示点颜色
indicator-active-color="red" 当前选中的指示点颜色
autoplay 是否自动切换
interval="2000" 自动切换间隔
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>

text组件的基本使用
-
selectable属性,实现长按选中文本内容的效果。
<view> <text selectable>12121313</text> </view>
rich-text组件的使用
<rich-text nodes="<h1 style='color:red;'>标题</h1>"></rich-text>

button组件
- 按钮组件
- 功能比HTML中的按钮丰富
- 通过open-type属性可以调用微信的功能
<!--pages/text/text.wxml-->
<view>~~~~~~通过type指定按钮类型~~~~~~</view>
<button>默认按钮</button>
<button type="primary">主色调按钮</button>
<button type="warn">警告按钮</button>
<view>~~~~~~size="mini"小尺寸按钮~~~~~~</view>
<button size="mini">默认按钮</button>
<button type="primary" size="mini">主色调按钮</button>
<button type="warn" size="mini">警告按钮</button>
<view>~~~~~~~~~~~plain镂空按钮~~~~~~~~~~~~</view>
<button size="mini" plain>默认按钮</button>
<button type="primary" size="mini" plain>主色调按钮</button>
<button type="warn" size="mini" plain>警告按钮</button>

image组件
- 图片组件
- 默认宽300px,高度240px

navigator组件
五、API
1、事件监听API
- 特点,以on开头,用来监听某些事件的触发
- wx.onWindowResize(function callback)监听窗口尺寸的变化
2、同步API
- 以Sync结尾的API都是同步API
- 同步API的执行结果,可以通过函数返回值直接获取,如果执行出错会抛出异常
- wx.setStorageSync('key','value')向本地存储写入内容
3、异步API
- 类似jquery中的$.ajax(options)函数,需要通过success、fail、complete接收调用的结果
- wx.request()发起网络请求,通过success回调函数接收数据
六、数据绑定
- data中定义
- WXML中使用数据。动态绑定数据。
-
动态绑定属性

- 三元运算

- 算数运算
<view>生成100以内的随机数{{radomNum1 * 100}}</view>
data: {
info:'hello world!',
imgsrc:'/images/343434.jpg',
radomNum:Math.random() * 10,
radomNum1:Math.random().toFixed(2)//两位小数的随机数 0.12
},
七、事件绑定
事件是渲染层到逻辑层的通讯方式。通过事件可以将用户在渲染层产生的行为,反馈到逻辑层进行业务的处理。

1、常见事件

2、事件对象的属性列表

3、target和currentTarget区别

4、bindtap触摸行为

5、在事件处理函数中为data中的数据赋值
<button type="primary" bindtap="fhandler">点我试试</button>
<view>加一{{count}}</view>
data: {
count:0,
},
fhandler(){
this.setData({
count: this.data.count +1,
})
},
6、事件传参 data-*参数名
<button bindtap="btnHandler" data-info="{{2}}">
事件传参
</button>
info被解析成参数的名字
数值2会被解析为参数的值
在事件处理函数中,通过 event.target.dataset.参数名即可获取到具体参数的值
btnHandler(event){
//dataset是一个对象,包含了所有通过data-* 传递过来的参数项
console.log(event.target.dataset.info)
}
7、bindinput语法-给把文本框绑定输入事件
<input bindinput="inputHandler"></input>
inputHandler(e){
console.log(e.detail.value)
}
8、实现文本框和data之间的数据同步
<input value="{{msg}}" bindinput="inputHandler"></input>
data:{
msg:'你好'
},
inputHandler(e){
this.setData({
msg:e.detail.value
})
input{
border:1px solid red;
margin: 5px;
padding: 5px;
border-radius: 5px;
}

八、条件渲染
1、wx:if
<view wx:if="{{type ===1}}">男</view>
<view wx:elif="{{type ===2}}">女</view>
<view wx:else>保密</view>
data:{
type:1
}
2、结合使用wx:if
如果一次性控制多个组件的展示与隐藏,可以使用一个
3、hidden
hidden="{{true}}"
4、wx:if和hidden对比
- 运行方式,wx:if是动态的创建和移除元素,控制元素的展示和隐藏。
- hidden以切换样式的方式。(display:none),控制。
- 频繁切换,使用hidden。
- 控制复杂时,使用wx:if
九、列表渲染
1、wx:for
通过wx:for可以根据指定的数组,循环渲染重复的组件结构。

循环项索引index,循环项用item。
2、手动指定索引和当前项变量名
- 使用wx:for-index可以指定当前循环项的索引的变量名
- wx:for-item可以指定当前项的变量名
<view wx:for="{{arr}}" wx:for-index="idx" wx:for-item='itemname'>
索引是:{{idx}},item项是:{{itemname}}
</view>
3、wx:key
<view wx:for="{{arr1}}" wx:key="id">
我是{{item.name}}
</view>
arr1:[
{id:1,name:'肖玉红'},
{id:2,name:"黛玉甜"},
{id:2,name:"送寺庙"}
],
十、wxss模板样式---css
1、rpx尺寸单位
750份

2、@import样式
@import"/common/common.wxss";
3、全局样式 app.wxss
十一、全局配置 app.josn

1、window


app.json
"window":{
"backgroundTextStyle":"dark",
"navigationBarBackgroundColor": "#94b452",
"navigationBarTitleText": "小兔子学小程序",
"navigationBarTextStyle":"white",
"enablePullDownRefresh": true,
"backgroundColor": "#2323bb"
},
2、tabBar-多页面快速切换

- backgroundColor:背景色
- selectedIconPath:选中时的图片背景
- borderStyle:tabBar上边框的颜色
- iconPath:未选中时的图片路径
- selectedColor:tab上的文字选中时的颜色
- color:文字默认颜色

"tabBar": {
"list": [{
"pagePath": "pages/index/index",
"text": "首页",
"iconPath":"/images/noactive.png",
"selectedIconPath":"/images/active.png"
},
{
"pagePath": "pages/text/text",
"text": "个人中心",
"iconPath":"/images/noactive.png",
"selectedIconPath":"/images/active.png"
}
]
},
十二、页面配置 xxx.json
页面配置会覆盖全局配置

十三、网络数据请求
- https
- 将接口的域名添加到信任列表中
1、配置小程序的合法域名
小程序的-》开发-》开发设置
2、GET请求
getInfo(){
wx.request({
url:"https://www.baidu.com",
methods:'GET',
data:{
name:'zf',
age:20
},
success:(res) => {
console.log(res)
}
})
}
3、POST请求
getInfo(){
wx.request({
url:"https://www.baidu.com",
methods:'POST',
data:{
name:'zf',
age:20
},
success:(res) => {
console.log(res)
}
})
}
4、onload()
/**
* 生命周期函数--监听页面加载
*/
onLoad(options) {
},
5、跳过request合法域名校验

6、跨域和ajax
跨域和Ajax都是基于浏览器的,而小程序依赖微信客户端,所以没有跨域,而且”发起网络数据请求“。
十四、案例-本地生活
- 新建项目并梳理项目结构
- 配置导航栏效果
- 配置tabBar效果
- 实现轮播图效果
- 实现九宫格效果
- 实习图片布局
1、新建项目local-life
在app.json中创建三个新的文件夹
"pages": [
"pages/home/home",
"pages/message/message",
"pages/contact/contact"
],
2、导航栏效果
"window": {
"backgroundTextStyle": "light",
"navigationBarBackgroundColor": "#2b4b6b",
"navigationBarTitleText": "本地生活",
"navigationBarTextStyle": "white"
},
3、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"
}
]
},
4、轮播图效果
data中定义数组,存储接受请求的数据。
data: {
swiperList:[],
gridList:[]
},
写请求方法
// 获取轮播图数据的方法
getSwiperList() {
wx.request({
url:'https://applet-base-api-t.itheima.net/slides',
method:'GET',
success:(res) =>{
this.setData({
swiperList:res.data
})
}
})
},
//九宫格数据
getGridList() {
wx.request({
url:'https://applet-base-api-t.itheima.net/categories',
method:'GET',
success:(res) =>{
//存储到data数组中
this.setData({
gridList:res.data
})
}
})
},
在onload中调用----类似mouted
/**
* 生命周期函数--监听页面加载
*/
onLoad(options) {
this.getSwiperList(),
this.getGridList()
},
页面
<!-- 轮播图 -->
<swiper class="swiper-container"
indicator-dots
ndicator-color="white"
indicator-active-color="red"
autoplay
interval="5000"
circular
>
<swiper-item wx:for="{{swiperList}}" wx:key="id">
<image src="{{item.image}}"></image>
</swiper-item>
</swiper>
<!-- 九宫格 -->
<view class="grid-list">
<view class="grid-item" wx:for="{{gridList}}" wx:key="id">
<image src="{{item.icon}}"></image>
<text>{{item.name}}</text>
</view>
</view>
<!-- 图片 -->
<view class="img-box">
<image src="/images/link-01.png" mode="widthFix"></image>
<image src="/images/link-02.png" mode="widthFix"></image>
</view>
css效果
/* pages/home/home.wxss */
.swiper-container {
height: 350rpx;
}
swiper image {
width: 100%;
height: 100%;
}
.grid-list{
display: flex;
/* 一行装不下,可以换行 */
flex-wrap: wrap;
border-top: 1rpx solid red;
border-left: 1rpx solid red ;
}
.grid-item{
width: 33.33%;
height: 200rpx;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
border-right: 1rpx solid red;
border-bottom: 1rpx solid red ;
box-sizing: border-box;
}
.grid-item image {
width: 60rpx;
height: 60rpx;
}
.grid-item text {
font-size: 24rpx;
margin-top: 10rpx;
}
.img-box{
display: flex;
padding: 20rpx 10rpx;
justify-content: space-around;
}
.img-box image {
width: 45%;
}
十五、页面导航---跳转
声明式导航
-
声明一个
导航组件,点击进行跳转。 -
<navigator url="/pages/message/message" open-type="switchTab">导航到消息列表</navigator> -
跳转到tabBar,open-type="switchTab"。
-
导航到非tabBar页面
-
<navigator url="/pages/info/info" open-type="navigate">看看爷爷</navigator> -
后退导航。open-type="navigatorBack",表示要后退的层级。delta值为数字,表示要退后的层级。
-
<navigator url="/pages/info/info" open-type="navigatorBack" delta='1'>退</navigator>
编程式导航
-
调用小程序的导航API,实现跳转。
-
导航到tabBar

<button bindtap="gotoMessage">跳转到消息页面</button>
gotoMessage(){
wx.switchTab({
url:'/pages/info/info'
})
}
- 导航到非tabBar
<button bindtap="gotoMessage">跳转到消息页面</button>
gotoMessage(){
wx.navigateTo({
url:'/pages/info/info'
})
}
- 后退导航
<button bindtap="goBack">跳转到消息页面</button>
goBack(){
wx.navigateBack()
}
导航传参
声明式导航传参:参数与路径之间使用 ? 间隔,参数值与参数值用 = 相连, 不同参数用&分隔。
<navigator url="/pages/info/info?name=zs&age=20">看看爷爷</navigator>
编程式导航传参:
<button bindtap="gotoMessage">跳转到消息页面</button>
gotoMessage(){
wx.navigateTo({
url:'/pages/info/info?name=zs&gender=20'
})
}
在onload中接受导航参数
/**生命周期函数--监听页面加载*/
onLoad(options) {
console.log(options)
},
十六、页面事件
下拉刷新
app.json window enablePullDownRefresh true
自动关闭下拉
wx.stopPullDownRefresh()
上拉触底
onReachBootom(){
}
上拉触底案例
-
定义随机获取颜色的方法
-
data: { colorList: [], //随机颜色的列表 isloading:false }, getColors() { this.setData({ isloading:true }) wx.showLoading({ title: '别着急,小主,在加载中呢...',//展示lodaing效果 }) wx.request({ url: 'https://applet-base-api-t.itheima.net/api/color', method: 'GET', success: function ({data:res}) { this.setData({ colorList:[...this.data.colorList, ...res.data] }) }.bind(this), fail:function(error){ console.log(error) }, complete:() => { wx.hideLoading() //隐藏加载效果 this.setData({ isloading:false }) } }) }, -
在页面加载时,获取初始颜色数据
-
渲染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: 350rpx; margin: 15rpx; text-align: center; text-shadow: 0rpx 0rpx 5rpx #fff; box-shadow: 1rpx 1rpx 6rpx #aaa; } -
在上拉触底时调用获取随机颜色的方法
-
onReachBottom() { // console.log('上拉触底,触发了!') if(this.data.isloading) return this.getColors() }, -
添加loading提示效果
-
对上拉触底进行节流处理
- 在data中定义isloading节流阀(默认为false)。true表示当前正在进行数据请求
- 在getColors()方法中修改isloading节流阀的值。在刚调用时,将节流阀设置成true。在网络请求complete回调函数中,将节流阀重置为false。
- 在onReachBottom()方法中判断节流阀的值,从而对数据请求进行节流控制。true,阻止。false,发起数据请求。

十七、自定义编译模式

十八、生命周期
应用生命周期函数
App({
//初始化,全局值触发一次
onLaunch(options){},
//启动时,从后台进入前台显示时触发
onshow(options){},
//小程序从前台进入后台时触发
onHide(){}
})
页面生命周期函数
onload onshow onReady onHide onShow pmUnload
十九、WXS脚本--过滤器
1、内嵌脚本
<view>{{m1.toUpper(username)}}</view>
<wxs module="m1">
//将文本转为大写形式
moudle.exports.toUpper = function(str){
return str.toUpperCase()
}
</wxs>
2、外联的wxs脚本
function(str){
return str.toUpperCase()
}
moudle.exports = {
toLower:toLower
}
引用
<wxs src='../../utils.tool.wxs' module="m1">
</wxs>
二十、案例-本地生活(列表页面)
创建shoplist文件夹
导航跳转-携带参数
<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>
动态设置当前页面的标题
wx.setNavigationTitle(Object object)
-
获取点击的title和id的值。在onLoad()方法中获取。并存储到data中
-
/** * 生命周期函数--监听页面加载 */ onLoad(options) { this.setData({ query: options }) }, -
在onReady()方法中调用。
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady() {
wx.setNavigationBarTitle({
title:this.data.query.title,
})
},
接口地址
-
https://applet-base-api-t.itheima.net/:cate_id/shop' -
:cate_id动态参数
-
GET请求
-
请求参数
-
_page表示请求第几页的数据 _limit表示请求几条数据
二十一、自定义组件
1、创建组件
- 在项目的根目录中,创建components ->test文件夹。
- 在新建的components ->test文件夹上,鼠标右键,点击”新建Component“
- 键入组件的名称之后会回车,会生成组件对应的4个文件。.js .json .wxml .wxss
2、引用组件
-
局部引用
-
//在页面的 .json文件中,引入组件 { "usingComponents":{ "my-test1":"/componrnts/test1/test1" } } //在页面的 .wxml文件中,使用组件。 <my-test1></my-test1> -
全局引用app.json
3、组件和页面的区别
- 组件的.json文件需要声明component:true属性
- 组件js文件调用的是component()函数
- 组件的事件处理函数需要定义到methods节点中
4、组件样式隔离-class
组件js文件中
Component({
options:{
styleIsoIlation:'isolated'
}
})
或者在json文件中
{
"styleIsolation":"isolated"
}

5、methods方法
6、properties属性

区别
- data更倾向于存储组件的私有数据
- properties存储外界传递到组件中的数据

7、数据监听器-watch
Component({
observers: {
'字段A,字段B': function(字段A的新值,字段B的新值) {
// do 'something
}
}
})
基本用法
Component({
data: { n1: 0,n2: 0,sum: 0},// 数据节点
methods: { // 方法列表
addN1() ( this.setData(( n1: this .data.n1 + 1 })
addN2() { this.setData({ n2: this.data.n2 + 1 })
observers: {// 数据监听节点
'n1, n2': function(n1, n2) {// 监听 n1 和 n2 数据的变化
this.setData({ sum: n1 + n2 }) // 通过监听器,自动计算 sum 的值
}
}
})
监听对象属性的变化
对象.属性A,对象.属性B
8、数据监听器案例
创建一个组件,全局引用。

app.json,之后引用
"usingComponents":{
"my-test1":"/components/test/test"
},
书写页面
<view style="background-color: rgb({{fullColor}});" class="colorBox">颜色值:
{{fullColor}}</view>
<button size="mini" bindtap="changeR" type="default">R</button>
<button size="mini" bindtap="changeG" type="primary">G</button>
<button size="mini" bindtap="changeB" type="warn">B</button>
<view>{{rgb.r}}--{{rgb.g}}--{{rgb.b}}</view>
.colorBox{
line-height: 200rpx;
font-size: 24rpx;
color: aliceblue;
text-shadow: 0 0 2rpx black;
text-align: center;
}
书写方法
// components/test/test.js
Component({
/**
* 组件的属性列表
*/
properties: {
},
/**
* 组件的初始数据
*/
data: {
rgb: {
r: 0,
g: 0,
b: 0
},
fullColor: '0,0,0'
},
/**
* 组件的方法列表
*/
methods: {
changeR() { //修改rgb对象上的r属性的值
this.setData({
'rgb.r': this.data.rgb.r + 5 > 255 ? 255 : this.data.rgb.r + 5
})
},
changeG() { //修改rgb对象上的g属性的值
this.setData({
'rgb.g': this.data.rgb.g + 5 > 255 ? 255 : this.data.rgb.g + 5
})
},
changeB() { //修改rgb对象上的b属性的值
this.setData({
'rgb.b': this.data.rgb.b + 5 > 255 ? 255 : this.data.rgb.b + 5
})
}
},
// 监听器
observers:{
'rgb.r,rgb.g,rgb.b':function(r,g,b){
this.setData({
fullColor:`${r},${g},${b}`
})
}
}
})
监听对象中所有属性的变化
// 监听器
observers:{
'rgb.**':function(obj){
this.setData({
fullColor:`${obj.r},${obj.rg},${obj.rb}`
})
}
}
9、纯数据字段
不用于界面渲染的data字段
有助于提升界面性能
使用规则
// components/test/test.js
Component({
options:{
//指定所有 _开头的数据字段为纯数据字段
pureDataPattern:/^_/
},
data: {
a:true, //普通数据字段
_b:true //纯数据字段
},
})
10、生命周期函数

Component({
lifetimes: {
attached: function() {
// 在组件实例进入页面节点树时执行
},
detached: function() {
// 在组件实例被从页面节点树移除时执行
},
},
// 以下是旧式的定义方式,可以保持对 <2.2.3 版本基础库的兼容
attached: function() {
// 在组件实例进入页面节点树时执行
},
detached: function() {
// 在组件实例被从页面节点树移除时执行
},
})
11、组件所在页面,生命周期。
| 生命周期 | 参数 | 描述 |
|---|---|---|
| show | 无 | 组件所在的页面被展示时执行 |
| hide | 无 | 组件所在的页面被隐藏时执行 |
| resize | Object Size |
组件所在的页面尺寸变化时执行 |
| routeDone | 无 | 组件所在页面路由动画完成时执行 |
Component({
pageLifetimes: {
show: function() {
// 页面被展示
},
hide: function() {
// 页面被隐藏
},
resize: function(size) {
// 页面尺寸变化
}
}
})
12、插槽占位
封装
<view>
<view>这是组件内部</view>
<slot></slot> /占位符/
</view>
使用者
<test>引用组件
<view>这是填充插槽的内容</view>
</test>
启用多个插槽
Component({
options: {
multipleSlots:true
}
})
<view>
<view>插槽1</view>
<slot name="nini"></slot>
<view>插槽2</view>
<slot name="mimi"></slot>
</view>
使用
<test>引用组件
<view slot="mimi">这是填充插槽的内容</view>
</test>
13、父子组件通信
-
属性绑定
-
用于父组件向子组件的指定属性设置数据,仅能设置JSON兼容的数据
//子组件的properties节点 properties:{ count:Number } //子组件的wxml结构,子组件使用父组件传递过来的值。 <text>子组件:count值{{count}}</text>子组件 <my-test1 count="{{count}}"></my-test1> 在父组件中,通过属性绑定,将count的值,传递给子组件的值。 父组件 <view>父组件中,值为{{count}}</view>
-
-
事件绑定
-
用于子组件向父组件传递数据,可以传递任意数据
1、在父组件的js中,定义一个函数,这个函数即将通过自定义事件的形式,传递给子组件 2、在父组件的wxml中,通过自定义事件的形式,将步骤1中定义的函数引用,传递给子组件 3、在子组件的js中,通过调用this.triggerEvent('自定义事件名',{参数对象}),将数据发送到父组件 4、在父组件的js中,通过调用e.detail获取子组件传递过来的数据//父组件message.js中 //在父组件的js中,定义一个函数,将函数传递给子组件。 Page({ data: { count:1 }, syncCount(e){ console.log('e',e) this.setData({ count:e.detail.value }) }, })//接受父组件的syncCount函数,将之起名sync <my-test2 count="{{count}}" bind:sync="syncCount"></my-test2> <view>父组件:{{count}}</view>//子组件test1.js,methods方法中 methods: { addCount(){ this.setData({ count:this.properties.count + 1 }) //触发自定义事件,将数值同步给父组件 this.triggerEvent('sync',{value:this.properties.count}) } }
-
-
获取组件实例
-
父组件可以通过this.selectComponent()获取子组件实例对象.id和class选择器
-
可以直接访问子组件的任意数据和方法
<my-test2 count="{{count}}" bind:sync="syncCount" class="goodman" id="gM"></my-test2> <view>父组件:{{count}}</view> <button bindtap="getChild">获取子组件的实例对象</button>getChild(){ const child = this.selectComponent('.goodman') console.log(child) child.setData({ count:child.properties.count + 1 }) // child.addCount() },
-
14、Behaviors
//调用Behaviors()方法,创建实例对象
//并使用module.exports 将behaviors实例对象
module.exports = Behavior({
//属性节点
properties:{},
//私有数据节点
data:{username:'zs'},
//事件处理函数和自定义方法节点
methods:{}
})
使用,引入组件js中。
//1.使用require()导入需要的自定义behavior模块
const myBehavior = require('../../behaviors/my-behavior')
Component({
//2.将导入的behavior实例对象,挂载到behaviors数组节点中,接口生效
behaviors:[myBehavior]
})
使用,页面。
<view>用户名:{{username}}</view>
同名字段的覆盖和组合规则
- 如果有同名的属性 (properties) 或方法 (methods):
- 若组件本身有这个属性或方法,则组件的属性或方法会覆盖
behavior中的同名属性或方法; - 若组件本身无这个属性或方法,则在组件的
behaviors字段中定义靠后的behavior的属性或方法会覆盖靠前的同名属性或方法; - 在 2 的基础上,若存在嵌套引用
behavior的情况,则规则为:引用者 behavior覆盖被引用的 behavior中的同名属性或方法。
- 若组件本身有这个属性或方法,则组件的属性或方法会覆盖
- 如果有同名的数据字段 (data):
- 若同名的数据字段都是对象类型,会进行对象合并;
- 其余情况会进行数据覆盖,覆盖规则为:
引用者 behavior>被引用的 behavior、靠后的 behavior>靠前的 behavior。(优先级高的覆盖优先级低的,最大的为优先级最高)
- 生命周期函数和 observers 不会相互覆盖,而是在对应触发时机被逐个调用:
- 对于不同的生命周期函数之间,遵循组件生命周期函数的执行顺序;
- 对于同种生命周期函数和同字段 observers ,遵循如下规则:
behavior优先于组件执行;被引用的 behavior优先于引用者 behavior执行;靠前的 behavior优先于靠后的 behavior执行;
- 如果同一个
behavior被一个组件多次引用,它定义的生命周期函数和 observers 不会重复执行。
二十二、npm包
- 不支持依赖于Node.js内置库的包
- 不支持依赖于浏览器内置对象的包
- 不支持依赖于C++插件的包
Vant Weapp
安装
npm i @vant/weapp@1.3.3 -S --production
将 app.json 中的 "style": "v2" 去除
工具 -> 构建 npm
使用,app.json
"usingComponents": {
"van-button": "@vant/weapp/button/index"
}
页面
<van-button type="warning">按钮</van-button>
定义css变量
html{
--main-color:red
}
.box1{
background-color: var(--main-color)
}
定制全局主题样式
在app.wxss中,写入css变量
page{
--button-danger-background-color:#C00000
}
api Promise化
npm i --save miniprogram-api-promise@1.0.4 然后npm构建,miniprogram_npm文件夹中才有
使用,在app.js中
//在小程序入口文件中,只需调用一次promisifyAll()方法
//即可实现异步API的Promise化
import {promisifyAll} from 'miniprogram-api-promise'
const wxp = wx.p = {}
promisifyAll(wx,wxp)
页面调用
<button bindtap="getinfo">
</button>
async getInfo() {
const {data:res} =await wx.p.request({
methods: 'GET',
url: 'https://applet-base-api-t.itheima.net/api/get',
data: {
name: 'zs',
age: 20
}
})
console.log(res)
},

二十三、全局数据共享
mobx-miniprogram配合mobx-miniprogram-bindings。
- mobx-miniprogram用来创建Store实例对象
- mobx-miniprogram-bindings用来Store的共享数据或方法,绑定到组件或页面中使用。
npm i --save mobx-miniprogram@4.13.2 mobx-miniprogram-bindings@1.2.1
创建一个store文件夹--store.js
// 在这个JS文件中,专门来创建Store的实例对象
import {observable,action} from'mobx-miniprogram'
export const store = observable({
nuA:1,
numB:2
})
将Store中的成员绑定到页面中
// pages/message/message.js
import {createStoreBindings} from 'mobx-miniprogram-bindings'
import {store} from '../../store/store'
Page({
/**
* 页面的初始数据
*/
data: {
count: 1
},
syncCount(e) {
// console.log('e',e)
this.setData({
count: e.detail.value
})
},
getChild() {
const child = this.selectComponent('.goodman')
console.log(child)
// child.setData({
// count:child.properties.count + 1
// })
child.addCount()
},
async getInfo() {
const {data:res} =await wx.p.request({
methods: 'GET',
url: 'https://applet-base-api-t.itheima.net/api/get',
data: {
name: 'zs',
age: 20
}
})
console.log(res)
},
/**
* 生命周期函数--监听页面加载
*/
onLoad(options) {
this.storeBindings = createStoreBindings(this,{
store,
fields:['numA','numB','sum'], //将这些字段绑定到this中
actions:['updateNum1']
})
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload() {
this.storeBindings.destoryStoreBindings()
},
})
在页面上使用Store中的成员
<!--message.wxml-->
<view>{{numA}}+{{numB}} = {{sum}}</view>
<van-button type="primary" bindtap="btnHander" data-step="{{1}}">num加1</van-button>
<van-button type="danger" bindtap="btnHander" data-step="{{-1}}">num减1</van-button>
btnHander(e) {
this.updateNum1(e.target.dataset.step)
},

将Store中的成员绑定到组件中
// components/test3/teste.js
import {storeBindingsBehavior} from 'mobx-miniprogram-bindings'
import {store} from '../../store/store'
Component({
behaviors:[storeBindingsBehavior],//通过storeBindingsBehavior来实现自动绑定
storeBindings:{
store,//指定要绑定的store
fields:{//指定要绑定的字段数据
numA:'numA',
numB:'numB',
sum:'sum'
},
actions:{
updateNum:"updateNum2"
}
},
})
在组件中使用Store中的成员--在组件teste.wxml中
<view>---------------------</view>
<view>{{numA}}+{{numB}} = {{sum}}</view>
<van-button type="warning" bindtap="btnHander2" data-step="{{1}}">num加1</van-button>
<van-button type="danger" bindtap="btnHander2" data-step="{{-1}}">num减1</van-button>
<view>---------------------</view>
在teste.js
// components/test3/teste.js
import {storeBindingsBehavior} from 'mobx-miniprogram-bindings'
import {store} from '../../store/store'
Component({
behaviors:[storeBindingsBehavior],//通过storeBindingsBehavior来实现自动绑定
storeBindings:{
store,//指定要绑定的store
fields:{//指定要绑定的字段数据
numA:'numA',
numB:'numB',
sum:'sum'
},
actions:{
updateNum:"updateNum2"
}
},
methods: {
btnHander2(e) {
// console.log(e)
this.updateNum(e.target.dataset.step)
}
}
})
二十四、分包
分包:把一个完整的小程序项目,按照需求划分为不同的子包,在构建时打包成不同的分包,用户在使用时按需进行加载。
- 优化小程序首次启动的下载时间
- 多人团队共同开的时候,更好的解耦。
构成

分包后:小程序项目有1个主包+多个分包组成
- 主包:一般只包含项目的启动页面或TabBar页面、以及所有分包都需要用到的一些公共资源
- 分包:只包含和当前分包有关的页面和私有资源

分包的加载规则
- 在小程序启动时,默认会下载主包并启动主包内页面
- tabBar页面需要放在主包中
- 当用户进入分包内某个页面时,客户端会把对应分包下载下来,下载完成后再进行展示
- 非tabBar页面可以按照功能的不同,划分为不同的分包之后,进行按需下载
- 分包大小不超过16M(主包+所有分包)
- 单个分包/主包大小不能超过2M
配置方法
目录结构
|——————app.js
|——————app.json
|——————app.wxss
|——————pages //主包的所有页面
| |——————index
| |——————logs
|——————packageA //第一个分包
| |——————pages
| |——————cat
| |——————dog
|——————packageA //第二个分包
| |——————pages
| |——————apple
| |——————banana
|------utils
app.json------在subpackage节点中声明分包的结构
{
"pages":[
"pages/home/home",
"pages/message/message",
"pages/contact/contact",
],
"subpackage":[
{
"root":"packageA",//第一个分包的根目录
"name": "p1",
"page":[
"pages/cat/cat",
"pages/dog/dog"
]
},
{
"root":"packageA",//第一个分包的根目录
"name": "p1",
"page":[
"pages/apple/apple",
"pages/banana/banana"
]
},
]
}
独立分包
{
"root":"packageA",//第一个分包的根目录
"name": "p1",
"page":[
"pages/apple/apple",
"pages/banana/banana"
],
"independent":true
},
分包预下载
app.json中
{
"preloadRule":{//分包预下载规则
"pages/contact/contact":{//触发分包预下载的页面路径
//network表示在指定的网络模式下进行预下载
//可选值:all(不限网络)和wifi
//默认值wifi
"network":"all",
//packages表示进入页面后,预下载哪些分包
//可以通过root或name指定预下载哪些分包
"packages":["pakA"]
}
}
}
二十五、自定义tabBar
- 配置信息
- 添加tabBar代码文件
- 编写tabBar代码
1. 配置信息
- 在
app.json中的tabBar项指定custom字段,同时其余tabBar相关配置也补充完整。 - 所有 tab 页的 json 里需声明
usingComponents项,也可以在app.json全局开启。
示例:
{
"tabBar": {
"custom": true,
"color": "#000000",
"selectedColor": "#000000",
"backgroundColor": "#000000",
"list": [{
"pagePath": "page/component/index",
"text": "组件"
}, {
"pagePath": "page/API/index",
"text": "接口"
}]
},
"usingComponents": {}
}
2. 添加 tabBar 代码文件
在代码根目录下添加入口文件:

custom-tab-bar/index.js
custom-tab-bar/index.json
custom-tab-bar/index.wxml
custom-tab-bar/index.wxss
3. 编写 tabBar 代码
用自定义组件的方式编写即可,该自定义组件完全接管 tabBar 的渲染。另外,自定义组件新增 getTabBar 接口,可获取当前页面下的自定义 tabBar 组件实例。
<van-tabbar active="{{ active }}" bind:change="onChange">
<van-tabbar-item wx:for="{{list}}" wx:key="index" info="{{item.info ? item.info : ''}}">
<image slot="icon" src="{{item.iconPath}}" mode="aspectFit" style="width: 25px; height: 25px;" />
<image slot="icon-active" src="{{item.selectedIconPath}}" mode="aspectFit" style="width: 25px; height: 25px;" />
{{item.text}}
</van-tabbar-item>
</van-tabbar>
import { storeBindingsBehavior } from 'mobx-miniprogram-bindings'
import { store} from '../store/store'
Component({
options: {
styleIsolation: 'shared',
},
behaviors:[storeBindingsBehavior],
storeBindings:{
store,
fields:{
sum:'sum'
},
actions:{
},
},
observers:{
'sum':function(val){
this.setData({
'list[1].info':val
})
}
},
data: {
active: 0,
"list": [{
"pagePath": "/pages/home/home.wxml",
"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",
info: 2
},
{
"pagePath": "pages/contact/contact",
"text": "联系我们",
"iconPath": "/images/tabs/contact.png",
"selectedIconPath": "/images/tabs/contact-active.png"
}
]
},
methods: {
onChange(event) {
this.setData({
active: event.detail
});
},
}
})

4、页面切换
methods: {
onChange(event) {
this.setData({
active: event.detail
})
wx.switchTab({
url:this.data.list[event.detail].pagePath,
})
},
}
5、选中项出错
将选中项的索引值,存放在store.js中
import { observable, action} from'mobx-miniprogram'
export const store = observable({
numA:1,
numB:2,
activeTabBarIndex:0, //索引值,初始为0
//计算属性:get只读
get sum(){
return this.numB + this.numA
},
// actions方法,用来修改store中的数据
updateNum1:action(function(step){
this.numA += step
}),
updateNum2:action(function(step){
this.numB += step
}),
//定义更新,索引值的方法。接受点击TabBar所产生的索引值。
updateactiveTabBarIndex:action(function(index){
this.activeTabBarIndex = index
})
})
在index.js中引入activeTabBarIndex值和更新索引值的方法
storeBindings:{
store,
fields:{
sum:'sum',
active:'activeTabBarIndex'
},
actions:{
updateActive:'updateactiveTabBarIndex'
},
},
当点击tabBar的时候,所产生的索引值,传递到store中。
methods: {
onChange(event) {
//调用更新索引值的方法,将点击的索引值传递过去
this.updateActive(event.detail)
wx.switchTab({
url:this.data.list[event.detail].pagePath,
})
},
}
页面使用
<van-tabbar active="{{active}}" bind:change="onChange">
</van-tabbar>
6、修改选中项文字颜色
<van-tabbar active="{{active}}" bind:change="onChange" active-color="#13A7A0">
</van-tabbar>

浙公网安备 33010602011771号