微信小程序-02
- (六)、小程序基础加强
- 1.自定义组件-组件的创建与引用
- (1).创建自定义组件
- (2).引用组件(全局和局部)
- (3).局部引用组件
- (4).全局引用组件
- (5).全局引用和局部引用的建议
- (6).组件和页面的区别
- 2.自定义组件-样式
- (1).组件样式隔离
- (2).组件样式隔离的注意点
- (3).修改组键的样式隔离选项
- 3.自定义组件-数据、方法和属性
- (1).data数据
- (2).methods 方法
- (3).properties属性 (父亲传数组给儿子)
- (4).data和properties的区别
- (5).使用setData修改properties的值
- 4.自定义组件- 数据监听器
- (1).什么是数据监听器
- (2).数据监听器的基本用法
- (3).监听对象属性的变化
- (4).自定义监听器的 - 案列
- (5).监听对象中所有属性的变化
- 5.自定义组件 - 纯数据字段
- (1).什么是纯数据字段
- (2).使用规则
- 6.自定义组件 - 组件的生命周期
- (1).组件全部的生命周期函数
- (2).组件主要的生命周期函数
- (3).Lifetimes 节点
- 7.自定义组件 - 组件所在页面的声明周期
- (1).什么是组件所在页面的周期
- (2).pageLifetimes 节点
- (3).利用生命周期函数 生成随机的颜色
- 8.自定义组件 - 插槽
- (1).什么是插槽
- (2).使用单个插槽
- (3).启用多个插槽
- 9.自定义组件 - 父子组件之间的通信
- (1).父子组件之间通信的3种方式
- (2).属性绑定 (父亲传递给儿子)
- (3).事件绑定 (儿子传递给父亲)
- (4).获取组件实列 (父组件获取子组件实列)
- 10.自定义组件-behavios
- (1).什么是behaviors
- (2).behaviors的工作方式
- (3).创建behavior
- (4).导入并使用 behavior
- (七)、npm
- 1.使用npm包
- (1).小程序对npm的支持与限制
- 2.使用npm包 - Vant Weapp
- (1).什么是Vant Weapp
- (2).安装 Vant 组件库
- (3).使用Vant 组件
- (4).定制全局主题样式
- 3.使用 npm 包 -API Promise 化
- (1). 基于回调函数的异步 API 的缺点
- (2).什么是 API Promise 化
- (3).实现 API Promise化
- (4).使用 API Promise 化
- (八)、全局数据共享
- 1.全局数据共享 - 概述
- (1).小程序中的全局数据共享方案
- 2.全局数据共享 - MobX
- (1).安装MobX相关的包
- (2).创建MobX的Store实列
- (3).将Store中的成员绑定到页面中
- (4).在页面上使用Store中的成员
- (5).将Store 中的成员绑定到组件
- (6).在组件中使用Store中的成员
- (九)、分包
- 1.分包 -概念
- (1).什么是分包
- (2).分包的好处
- (3).分包前项目的构成
- (4).分包后项目的构成
- (5).分包的加载机制
- (6).分包的体积限制
- 2.分包 - 使用分包
- (1).配置方法
- (2).打包原则
- (3).引用原则
- 3.分包 - 独立分包
- (1).什么是独立分包
- (2).独立分包和普通分包的区别
- (3).独立分包的应用场景
- (4).独立分包的配置方法
- (5).引用原则
- 4.分包 - 分包预下载
- (1).什么是分包预下载
- (2).配置分包的预下载
- (3).分包预下载的限制
- 5.案列 - 自定义 tabBar
- (1).本案列主要用到的知识点
- (2).实现步骤
- (3).配置信息
- (4).添加tabBar代码文件
- (5).渲染tabBar上的数字徽标
- (5).实现tabBar页面的切换
- (7).设置选中文本框的颜色
(六)、小程序基础加强
1.自定义组件-组件的创建与引用
(1).创建自定义组件
- 在项目的根目录中,鼠标右键,创建
compoents->test
文件夹。 - 在新建的
components->test
文件夹上,鼠标右键,点击"新建Component
" - 键入组件的名称之后回车,会自动生成组件对应的4个文件,后缀分别为 .js .json .wxml .wxss。
- 注意:为了保证目录结构的清晰,建议把不同的组件,存放到单独目录中。
(2).引用组件(全局和局部)
组件的引用方式分为: "局部引用"和 “全局引用”,顾名思义:
- 局部引用: 组件只能在当前被引用的页面内使用。
- 全局引用: 组件可以在每个小程序中使用。
(3).局部引用组件
在页面的.json配置文件中引用组件的方式,叫做"局部引用"。
home.wxss
引用组件的操作:
{
"usingComponents": {
"my-test1":"/components/test/test"
}
}
home.wxml
使用组件的操作
<!--pages/home/home.wxml-->
<text>首页</text>
<my-test1></my-test1>
其他页面并不会展示这个组件的信息
(4).全局引用组件
我们只需在app.json的位置出,与window平级编写以下配置即可
"usingComponents": {
"my-test1":"/components/test/test"
},
(5).全局引用和局部引用的建议
- 多个页面需要使用->全局
- 单个页面需要使用->局部
(6).组件和页面的区别
从表面来看,组件和页面都是由. js 、.json、.wxml和.wxss着四个文件组成的。但是组件和页面的.js与.json文件明显不同。
- 组件的.json文件中需要声明:"
component:true
"属性。 - 组件的.js文件中调用的是
Component()
函数不是Page()
。 - 组件的事件处理函数需要定义到methods节点中。
组件的js文件
// components/test/test.js
Component({
/**
* 组件的属性列表
*/
properties: {
},
/**
* 组件的初始数据
*/
data: {
},
/**
* 组件的方法列表
*/
methods: {
}
})
组件的.json
{
"component": true,
"usingComponents": {}
}
2.自定义组件-样式
(1).组件样式隔离
默认情况下,自定义组件的样式只对当前组件生效,不会影响组件之外的UI结构,如图所示:
- 组件A的样式不会影响组件C的样式。
- 组件A的样式不会影响小程序页面的样式。
- 小程序页面的样式不会影响组件A和C的样式。
(2).组件样式隔离的注意点
- app.wxss中的全局样式对组件无效
- 只有class选择器会有样式隔离效果,
id选择器、属性选择器、标签选择器不受样式隔离的影响
。
建议: 在组件和引用组件的页面中建议使用class选择器,不要id、属性、标签选择器。
(3).修改组键的样式隔离选项
默认情况下,自定义组件的样式隔离性能够防止组件内外样式互相干扰的问题。但有时,我们需要在外界能够控制组件内部的样式,此时,可以通过stylesolation修改组件的样式隔离选项。
进行隔离->互不影响
1. 第一种:在组件的 .js文件中新增如下配置
Component({
// 隔离性
options:{
styleIsolation:'isolated'
},
}
2. 第二种:在组件的.json文件中新增如下配置
{
styleIsolation:'isolated'
}
styleIsolation
参数 描述
`互相隔离`
isolated 表示启用样式隔离,再定以组件内外,使用class指定的样式将不会相互影响。
`外面会影响到组件,组件不会影响到外部`
apply-shared 表示页面wxss样式将影响到自定义组件,但自定义组件wxss中指定的样式不会影响页面。
`组件会影响到外部,外部不会影响到组件`
shared 表示页面wxss样式将影响到自定义组件,自定义组件wxss中指定的样式也会影响页面和其他设置乐 apply-shared或shared的自定义组件。
3.自定义组件-数据、方法和属性
(1).data数据
在小程序组件中,用于组件模板渲染的私有数据,需要定义到data节点中:
组件.wxml
<!--components/test/test.wxml-->
<text>components/test/test.wxml</text>
<view>
<text>{{count}}</text>
</view>
组件.js test.js
// components/test/test.js
Component({
// 隔离性
options:{
styleIsolation:'isolated'
},
/**
* 组件的属性列表
*/
properties: {
},
/**
* 组件的初始数据
*/
data: {
count:0
},
/**
* 组件的方法列表
*/
methods: {
}
})
(2).methods 方法
在小程序组件中,事件处理函数和自定义方法需要定义到methods节点中:
自定义的方法:我们要养成一个规范:以下划线开头。事件处理函数我们不以下划线开头!!!
test.js
// components/test/test.js
Component({
// 隔离性
options:{
styleIsolation:'isolated'
},
/**
* 组件的属性列表
*/
properties: {
},
/**
* 组件的初始数据
*/
data: {
count:0
},
/**
* 组件的方法列表
*/
methods: {
// 1. 自增事件处理函数...
addCount(){
this.setData({
count:this.data.count+1
})
this._showCount();
},
_showCount(){ // 2. 提示框的操作
wx.showToast({
title: '点击按钮:'+ this.data.count,
})
}
}
})
test.wxml
<!--components/test/test.wxml-->
<text>components/test/test.wxml</text>
<view>
<text>{{count}}</text>
</view>
<button type="primary" bindtap="addCount">按我+1</button>
(3).properties属性 (父亲传数组给儿子)
在小程序组件中,properties是组件的对外属性,用来接受外界传递到组件的数据
,实列实列代码如下
properties: {
// 1. 第一种方式: 简化的方式->无法指定默认值
// max:Number,
// 2. 第二种方式: 完整的定义方式 [当需要指定属性默认值时,建议使用此方式]
max:{
type:Number, // 属性值的数据类型
value:10 // 属性默认值
}
},
组件 test.js
// components/test/test.js
Component({
// 隔离性
options:{
styleIsolation:'isolated'
},
/**
* 组件的属性列表
*/
properties: {
// 1. 第一种方式: 简化的方式->无法指定默认值
// max:Number,
// 2. 第二种方式: 完整的定义方式 [当需要指定属性默认值时,建议使用此方式]
max:{
type:Number, // 属性值的数据类型
value:10 // 属性默认值
}
},
/**
* 组件的初始数据
*/
data: {
count:0
},
/**
* 组件的方法列表
*/
methods: {
// 1. 自增事件处理函数...
addCount(){
if(this.data.count>=this.properties.max) return
this.setData({
count:this.data.count+1
})
this._showCount();
},
_showCount(){ // 2. 提示框的操作
wx.showToast({
title: '点击按钮:'+ this.data.count,
})
}
}
})
父home.wxml
<!--pages/home/home.wxml-->
<text class="t1">首页</text>
<my-test1 max="4"></my-test1>
(4).data和properties的区别
在小程序的组件中,properties属性和data数据的用法相同、它们都是可读可写的,只不过:
- data 更倾向于存储组件的私有数据。
- properties 更倾向于存储外界传递到组件中的数据。
- data和properties的引用地址时相同的…
(5).使用setData修改properties的值
由于data数据和properties属性在本质上没有任何区别,因此properties属性的值也可以用于页面的渲染,或使用setData为properties中的属性重新赋值。
// components/test/test.js
Component({
// 隔离性
options:{
styleIsolation:'isolated'
},
/**
* 组件的属性列表
*/
properties: {
// 1. 第一种方式: 简化的方式->无法指定默认值
// max:Number,
// 2. 第二种方式: 完整的定义方式 [当需要指定属性默认值时,建议使用此方式]
max:{
type:Number, // 属性值的数据类型
value:10 // 属性默认值
}
},
/**
* 组件的初始数据
*/
data: {
count:0
},
/**
* 组件的方法列表
*/
methods: {
// 1. 自增事件处理函数...
addCount(){
this.setData({
count:this.data.count+1,
max:this.properties.max+1
})
this._showCount();
},
_showCount(){ // 2. 提示框的操作
wx.showToast({
title: '点击按钮:'+ this.data.count,
})
}
}
})
4.自定义组件- 数据监听器
(1).什么是数据监听器
数据监听器用途用于监听和响应任何数据字段的变化,从而执行特定的操作。它的作用类似于Vue中的watch侦听器
。在小程序组件中。
(2).数据监听器的基本用法
1. 在components新建一个文件夹
2. 在这个新建的文件夹中引入compoents
3. 在app.json文件中配置注册 新建的这个组件
4. 在app.wxml文件中使用我们新建的这个组件
test2.js
初始化数据并设置监听的方法
/**
* 组件的监听器-> 假如说监听的数据发生了变化,那么就会触发这个事件
*/
observers:{
'n1,n2':function(newN1,newN2){ // 左边是监听的数据,右侧是方法(监听到的新值)
this.setData({
sum:newN2+newN1
})
}
}
// components/test2/test2.js
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(newN1,newN2){ // 左边是监听的数据,右侧是方法(监听到的新值)
this.setData({
sum:newN2+newN1
})
}
}
})
test2.wxml
<!--components/test2/test2.wxml-->
<view>
{{n1}}+{{n2}}={{sum}}
</view>
<button bindtap="addN1">n1+1</button>
<button bindtap="addN2">n2+1</button>
(3).监听对象属性的变化
数据监听器支持监听对象中单个或多个属性的变化。
Component({
obervers:{
'对象.属性1,对象.属性2':function(新属性A的值,新属性B的值){
// 事件触发的三种情况
1. 属性A的值发生了变化
2. 属性B的值发生了变化
3. 直接为整个对象发生了变化
}
}
})
(4).自定义监听器的 - 案列
注意点: 假如我们data区域的是对象。我们想要给对象里的某一个属性赋值:我们需要用单引号括起来
this.setData({
'对象.属性名1':
})
test3.js
// components/test3/test3.js
Component({
/**
* 组件的属性列表
*/
properties: {
},
/**
* 组件的初始数据
*/
data: {
rgb:{
r:0,
g:0,
b:0
},
fullColor:'0,0,0'
},
observers:{
'rgb.r,rgb.g,rgb.b':function(newR,newG,newB){
this.setData({
fullColor:newR+','+newG+','+newB
})
}
},
/**
* 组件的方法列表
*/
methods: {
changeR(){
if(this.data.rgb.r>255) return
this.setData({
'rgb.r':this.data.rgb.r+10
})
},
changeG(){
if(this.data.rgb.g>255) return
this.setData({
'rgb.g':this.data.rgb.g+10
})
},
changeB(){
if(this.data.rgb.b>255) return
console.log()
this.setData({
'rgb.b':this.data.rgb.b+10
})
}
}
})
test3.wxml
<!--components/test3/test3.wxml-->
<view style="background-color: rgb({{fullColor}}); width: 100%;height: 300rpx">
</view>
<view>0
背景颜色的RGB值为: {{fullColor}}
</view>
<view style="text-align: center;margin-top: 45rpx;">
<button type="default" size="mini" bindtap="changeR">R</button>
<button type="primary" size="mini" bindtap="changeG">G</button>
<button type="warn" size="mini" bindtap="changeB">B</button>
</view>
(5).监听对象中所有属性的变化
如果某个对象中需要被监听的属性太多,为了方便,可以使用通配符 ** 来监听对象中的所有属性的变化:
我们在使用欸都时候,需要用到通配符和反引号
observers:{
'rgb.**':function(obj){
this.setData({
fullColor:`${obj.r},${obj.g},${obj.b}`
})
}
},
5.自定义组件 - 纯数据字段
(1).什么是纯数据字段
概念: 纯数据字段指的是那些不用于界面渲染的data字段。
应用场景: 列如有些情况下,某些data中的字段既不会展示在界面上,也不会传递给其他组件。仅仅在当前组件内部使用。带有这种特性的data字段适合设置为纯数据字段。
(2).使用规则
在Component构造器的options节点中,指定 pureDataPattern为一个正则表达式,字段名符合这个正则表达式的字段将成为纯数据字段。
6.自定义组件 - 组件的生命周期
(1).组件全部的生命周期函数
生命周期函数 | 参数 | 描述说明 |
---|---|---|
created | 无 | 在组建刚刚被创建的时候执行 |
attached | 无 | 在组件实列进入页面节点树时执行 |
ready | 无 | 在组件在视图层布局完成后执行 |
moved | 无 | 在组建实列被移动到节点树另一个位置时执行 |
detached | 无 | 在组件实列被从页面节点数移除时执行 |
error | 无 | 每当组件方法抛出错误时执行 |
(2).组件主要的生命周期函数
在小程序组件中,最重要的生命周期函数有3个,分别是" created、attached、detached。"
- 组件实列
刚被创建好的时候
,created生命周期函数会被触发
-
- 此时还不能调用 setData
-
- 通常在这个生命周期函数中,只应该用于给组件的this添加一些自定义的属性字段。
- 在
组件完全初始化完毕、进入页面节点树后
,attached生命周期函数才会触发
-
- 此时,this.data已被初始化完毕
-
- 这个生命周期很有用,绝大多数初始化的工作可以在这个时机进行(比如: 请求获取初始化的数据)
- 在组件离开页面节点树后,detached生命周期函数会被触发
-
- 退出一个页面时,会触发页面内每一个自定义组件的detached生命周期函数
-
- 此时适合做一些清理性质的工作
(3).Lifetimes 节点
在小程序组件中,生命周期函数可以直接定义在Component构造器的第一季参数中,可以在lifetimes字段内进行声明(这是推荐的方式,其优先级最高)
lifetimes:{
created(){
console.log("被创建了")
},
attached(){
console.log('所有的数据初始化完毕')
}
},
7.自定义组件 - 组件所在页面的声明周期
(1).什么是组件所在页面的周期
有时候,自定义组件的行为依赖于页面状态的变化,此时就需要用到组件所在页面的声明周期。
每当触发页面的show生命周期的函数时候,我们希望能够重新生成一个随机的RGB颜色值。
在自定义组件中,塑件所在页面的生命周期函数有如下3个:
生命周期函数 参数 描述
show 无 组件所在的页面被展示时执行
hide 无 组件所在的页面被隐藏时执行
resize object Size 组件所在的页面尺寸发生变化时执行
(2).pageLifetimes 节点
// components/test3/test3.js
Component({
pageLifetimes:{// 页面在组件的生命周期
show(){
console.log('show')
},
hide(){
console.log('hide')
},
resize(){
console.log('resize')
}
},
lifetimes:{ // 组件的生命周期
created(){
console.log("被创建了")
},
attached(){
console.log('所有的数据初始化完毕')
}
}
})
(3).利用生命周期函数 生成随机的颜色
lifetimes:{ // 组件的生命周期
created(){
console.log("被创建了")
},
attached(){
console.log('所有的数据初始化完毕')
this.setData({
fullColor:Math.random()*256+','+Math.random()*256+','+Math.random()*256
})
console.log(this.data.fullColor)
}
},
8.自定义组件 - 插槽
(1).什么是插槽
再打自定义组件的wxml结构中,可以提供一个< slot>节点(插槽),用于承载组件使用者提供的wxml结构。
(2).使用单个插槽
在小程序中,默认每个自定义组件中只允许使用一个 < slot>进行占位,这种个数上的限制叫做单个插槽。
test4.js
<!--components/test4/test4.wxml-->
<view>
<view>
这里是组件的内部结构
</view>
<!-- 1. 设置插槽 -->
<slot></slot>
</view>
home.wxml
<!--pages/home/home.wxml-->
<text class="t1">首页</text>
<my-test4>
<view>
这是通过插槽填充的数据
</view>
</my-test4>
(3).启用多个插槽
在小程序的自定义组件中,需要使用多 < slot> 插槽时,可以在组件的.js文件中。通过以下的方式进行启用,默认的是一个插槽:
test4.js
// components/test4/test4.js
Component({
options:{
multipleSlots:true
}
})
test4.wxml
用name取别名
<!--components/test4/test4.wxml-->
<view>
<slot name="before"></slot>
<view>
这里是组件的内部结构
</view>
<!-- 1. 设置插槽 -->
<slot name="after"></slot>
</view>
home.wxml
通过slot属性进行绑定
<!--pages/home/home.wxml-->
<text class="t1">首页</text>
<my-test4>
<view slot="before">
这是通过插槽填充的数据
</view>
</my-test4>
9.自定义组件 - 父子组件之间的通信
(1).父子组件之间通信的3种方式
- 属性绑定
-
- 用于父组件向子组件的指定属性设置数据,仅能设置JSON兼容的数据
- 事件绑定
-
- 用于子组件向父组件传递数据,可以传递任意数据
- 获取组件实列
-
- 父组件还可以通过 this.selectComponent()获取组件实列
-
- 这样就可以直接访问子组件的任意数据和方法
(2).属性绑定 (父亲传递给儿子)
属性绑定
用于实现父向子传值
,而且只能传递普通类型的数据
,无法将方法传递给子组件。
- 父亲组件
// 父组件的 data 节点
data:{
count:0
}
// 父组件的wxml结构 count="{{count}}"
<my-test3 count="{{count}}"></my-test3>
<view>{{count}}</view>
- 子组件
我们子组件在properties节点种声明对应的属性并使用
// 子组件的 properties 节点
properties:{
count:Number
}
// 子组件的wxml结构
<text>子组件->{{count}}</text>
- 父亲传递函数
home.wxml
<!--pages/home/home.wxml-->
<text class="t1">首页</text>
<view>
父组件中Count的值为: {{count}}
</view>
<view>
---------------
</view>
// 传递函数
<my-test5 count="{{count}}"></my-test5>
- 儿子组件接受参数
tes5t.js
// components/test5/test5.js
Component({
/**
* 组件的属性列表
*/
properties: {
// 注册-> 第一个是注册的变量名,第二个是注册的变量类型
count: Number
},
/**
* 组件的初始数据
*/
data: {
},
/**
* 组件的方法列表
*/
methods: {
}
})
- 儿子组件输出传递过来的组件
test5.wxml
<!--components/test5/test5.wxml-->
<text>父组件传递过来的数据为 : {{count}}</text>
- 儿子调用自增的函数
test5.wxml
<!--components/test5/test5.wxml-->
<text>父组件传递过来的数据为 : {{count}}</text>
<button type="primary" bindtap="addCount">点我+1</button>
test5.js
// components/test5/test5.js
Component({
/**
* 组件的属性列表
*/
properties: {
// 注册-> 第一个是注册的变量名,第二个是注册的变量类型
count: Number
},
/**
* 组件的初始数据
*/
data: {
},
/**
* 组件的方法列表
*/
methods: {
addCount(){
console.log(this)
this.setData({
count:this.properties.count+1
})
}
}
})
(3).事件绑定 (儿子传递给父亲)
事件绑定用于实现子向父传值,可以传递任何类型的数据。
1.在父组件的js中,定义一个函数,这个函数即将通过自定义事件的形式,传递给子组件
2.在父组件的wxml中,通过自定义事件的形式,将步骤1中定义的函数引用,传递给子组件
3.在子组件的js中,通过调用this.triggerEvent('自定义事件名',{/* 参数对象*/}),将数据传递给父组件
4.在父组件的js中,通过e.detail获取到子组件传递过来的数据
- 父组件定义一个函数
home.js
Page({
syncCount(){
console.log('syncCount')
},
/**
* 页面的初始数据
*/
data: {
count:0
},
})
- 父组件将定义的方法传递给子组件
home.wxml
<!--pages/home/home.wxml-->
<text class="t1">首页</text>
<view>
父组件中Count的值为: {{count}}
</view>
<view>
---------------
</view>
<!-- bind:自定义事件名="方法名" -->
<my-test5 count="{{count}}" bind:syc1="syncCount"></my-test5>
- 子组件绑定触发事件
test5.js
// components/test5/test5.js
Component({
/**
* 组件的属性列表
*/
properties: {
// 注册-> 第一个是注册的变量名,第二个是注册的变量类型
count: Number
},
/**
* 组件的初始数据
*/
data: {
},
/**
* 组件的方法列表
*/
methods: {
addCount(){
this.setData({
count:this.properties.count+1
})
// 触发自定义事件,将数值同步给父组件.。 第一个参数是: 自定义事件名,第二个参数是: 传给父类的数据{value:''}
this.triggerEvent('syc1',{value:this.properties.count})
}
}
})
- 父组件进行同步接受数据
test5.js
Page({
syncCount(e){
console.log('syncCount',e)
this.setData({
count:e.detail.value
})
},
/**
* 页面的初始数据
*/
data: {
count:0
}
})
(4).获取组件实列 (父组件获取子组件实列)
可在父组件里调用 this.selectComponent(“id或class选择器”),获取子组件的实列对象,从而直接访问子组件的任意数据和方法。调用时需要传入一个选择器。
home.wxml
<!--pages/home/home.wxml-->
<text class="t1">首页</text>
<view>
父组件中Count的值为: {{count}}
</view>
<view>
---------------
</view>
<!-- bind:自定义事件名="方法名" -->
<my-test5 count="{{count}}" bind:syc1="syncCount" class="customerA"></my-test5>
<button type="warn" bindtap="getChild">获取子组件的实列对象</button>
home.js
Page({
getChild(){
// 这里我们通过类选择器获取实列,并用e接受
const e=this.selectComponent('.customerA')
console.log('子组件的实列->',e)
// 我们改变这个count值。注意这里我们不能用this,因为this是父组件并不是子组件。所以我们要用子组件的实列对象进行操作。
e.setData({
count:e.data.count+10
})
},
syncCount(e){
console.log('syncCount',e)
this.setData({
count:e.detail.value
})
},
/**
* 页面的初始数据
*/
data: {
count:0
}
})
10.自定义组件-behavios
(1).什么是behaviors
behaviors是小程序中,用于实现组件间代码共享的特性,类似于Vue.js中的 “mixins”
(2).behaviors的工作方式
每个 behavioor 可以包含一组属性、数据、生命周期函数和方法。组件引用它时,它的属性、数据和方法会被合并到组件中
。
每个组件可以引用多个behavior
,behavior也可以引用其他的 behavior。
(3).创建behavior
调用 Behavior方法即可创建一个共享的 behavior 实列对象,供所有的组件使用:
我们在根目录下创建Behavior这个文件夹中创建一个文件 behavior.js
my-behaviors.js
// 1. 创建一个Behavior并共享出里面的数据
module.exports= Behavior({
data:{
username:'jsxs'
},
properties:{},
methods:{}
})
(4).导入并使用 behavior
在组件中,使用 require()
方法导入需要的behavior,挂载后 即可访问 behavior中的数据或方法
。
test5.js
// 1.在我们要用的组件的 .js上面的文件中引入我们自定义的共享数据
const myBehavior=require('../../behaviors/my-behavior')
// 2. 进行数据的挂载
behaviors:[myBehavior],
// components/test5/test5.js
// 1.在我们要用的组件的 .js上面的文件中引入我们自定义的共享数据
const myBehavior=require('../../behaviors/my-behavior')
Component({
// 2. 进行数据的挂载
behaviors:[myBehavior],
/**
* 组件的属性列表
*/
properties: {
// 注册-> 第一个是注册的变量名,第二个是注册的变量类型
count: Number
},
/**
* 组件的初始数据
*/
data: {
},
/**
* 组件的方法列表
*/
methods: {
addCount(){
this.setData({
count:this.properties.count+1
})
// 触发自定义事件,将数值同步给父组件.。 第一个参数是: 自定义事件名,第二个参数是: 传给父类的数据{value:''}
this.triggerEvent('syc1',{value:this.properties.count})
}
}
})
test5.wxml
我们继续通过Mustach语法进行获取数据
<!--components/test5/test5.wxml-->
<text>父组件传递过来的数据为 : {{count}}</text>
<view>
通过behavior获取的数据: {{username}}
</view>
<button type="primary" bindtap="addCount">点我+1</button>
(七)、npm
1.使用npm包
(1).小程序对npm的支持与限制
目前,小程序已经支持使用 npm 安装第三方包,从而来提高小程序的开发效率,但是,在小程序中使用npm包有3个限制:
- 不支持依赖于
Node.js
内置库的包 - 不支持依赖于
浏览器内置对象
的包 - 不支持依赖于
C++
插件的包
总结: 虽然npm上的包有千千万,但是能够供小程序使用的包却:“为数不多”。
2.使用npm包 - Vant Weapp
(1).什么是Vant Weapp
Vant Weapp是有赞助前端团队开源的小程序UI组件库,助理于开发者快速搭建小程序应用。它所使用的是 MIT开源许可协议,对商业使用比较友好。
官方文档地址: https://vant-contrib.gitee.io/vant-weapp/#/home
(2).安装 Vant 组件库
在小程序项目中,安装Vant组件库主要分为如下3步:
初始化项目
npm init -y
- 通过 npm 安装 (建议指定版本为 @1.3.3)
npm i @vant/weapp@1.3.3 -S --production
- 构建npm包
新版本不用去本地设置里面勾选了
- 修改app.json
(3).使用Vant 组件
安装完 Vant 组件库之后,可以在app.json
的usingComponents
节点中引入需要的组件,即可在wxml中直接使用组件。
- 在app.json这个文件中写
home.json
"usingComponents": {
"van-button": "@vant/weapp/button/index"
},
home.wxml
<!--pages/home/home.wxml-->
<text class="t1">首页</text>
<van-button type="default">默认按钮</van-button>
<van-button type="primary">主要按钮</van-button>
<van-button type="info">信息按钮</van-button>
<van-button type="warning">警告按钮</van-button>
<van-button type="danger">危险按钮</van-button>
(4).定制全局主题样式
- 介绍全局主题样式
Vant Weapp 使用CSS变量来实现定制主题。关于CSS变量的基本用法: 请参考MDN文档。
https://developer.mozilla.org/zh-CN/docs/Web/CSS/Using_CSS_custom_properties
自定义属性(有时也被称作CSS变量或者级联变量)是由CSS作者定义的,它包含的值可以在整个文档中重复使用。由自定义属性标记设定值(比如: --main-color: black;
),由 var() 函数来获取值(比如: color: var(–main-color);
)
复杂的网站都会有大量的CSS代码,通常也会有许多重复的值。
举例:同样一个颜色值可能在成千上百个地方被使用到,如果这个值发生了变化,需要全局搜索并且一个一个替换
。自定义属性在某个地方存储一个值,然后在其他许多地方引用它。另一个好处是语义化的标识。如:–main-text-color
会比 #00ff00 更易理解,尤其是这个颜色值在其他上下文中也被使用到。自定义属性受级联的约束,并从其父级继承其值。
--main-bg-color: brown;
background-color: var(--main-bg-color);
- 定制全局主题样式
在app.wxss中,写入CSS变量,即可对全局生效:
1. 为什么要用page做节点?
2. 为什么名字是这些?
app.json
/**app.wxss**/
.container {
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
padding: 200rpx 0;
box-sizing: border-box;
}
/* 我们在这里为什么要使用page节点. */
page{
/* 为什么我们的按钮名字是这些? https://github.com/youzan/vant-weapp/blob/dev/packages/common/style/var.less */
--button-danger-background-color: #C00000;
--button-danger-border-color: #D60000;
}
home.wxml
<!--pages/home/home.wxml-->
<text class="t1">首页</text>
<van-button type="default">默认按钮</van-button>
<van-button type="primary">主要按钮</van-button>
<van-button type="info">信息按钮</van-button>
<van-button type="warning">警告按钮</van-button>
<van-button type="danger">危险按钮</van-button>
源码
根节点
3.使用 npm 包 -API Promise 化
(1). 基于回调函数的异步 API 的缺点
默认情况下,小程序官方提供的异步API 都是基于回调函数实现的,列如: 网络请求的API需要按照如下的方式调用:
wx.request({
method: '',
url:'',
data:{},
success:()=>{}, // 请求成功的回调函数
fail:()=>{}, // 请求失败的回调函数
complete:()=>{} // 请求完成的回调函数
})
缺点: 容易造成回调地狱的问题,代码的可读性、维护性差!
(2).什么是 API Promise 化
API Promise化
,指的是提供额外的配置
,将官方提供的、基于回调函数的异步API,升级改造为基于Pormise的异步API
,从而提高代码的可读性、维护性,维护性,避免回调地狱的问题。
(3).实现 API Promise化
在小程序中,实现API Promise化主要依赖于 miniprogram-api-promise
这个第三方的npm包。
npm i --save miniprogram-api-promise@1.0.4
记住: 我们每次在微信小程序安装一个包,我们不能够立马进行使用,我们需要重新构建npm。
第一步: 删除包
第二步 重新构建
第三步: 成功之后
(4).使用 API Promise 化
- 第一步在 app.js中引入
app.js
在小程序入口文件中(app.js),只需调用一次promisifyAll()方法.即可实现异步 API 的promise化。
// app.js
import {promisifyAll} from 'miniprogram-api-promise'
const wxp=wx.p={}
promisifyAll(wx,wxp)
- 在home.wxml
hoem.xml
绑定方法
<!--pages/home/home.wxml-->
<text class="t1">首页</text>
<van-button type="primary" bindtap="getinfo">默认按钮</van-button>
- 在home.js
Page({
async getinfo(){
const res= await wx.p.request({
method:'GET',
url:'https://applet-base-api-t.itheima.net/api/get',
data:{
name:'zs',
age:20
}
})
console.log(res)
},
})
不去掉关键字
去掉关键字
(八)、全局数据共享
1.全局数据共享 - 概述
全局数据共享 (又叫做: 状态管理)是为了解决组件之间数据共享的问题。
开发中常用的全局数据共享方案有: Vuex、Redux、MobX等等。
(1).小程序中的全局数据共享方案
在小程序中,可使用 mobx-miniporgram
配合 mobx-miniporgram-bindings
实现全局数据共享。
- mobx-miniporgram 用来
创建Store实列对象
。 - mobx-miniporgram-bindings 用来
把Store中的共享数据或方法,绑定到组件或页面中使用
。
2.全局数据共享 - MobX
(1).安装MobX相关的包
在项目中运行如下的命令,安装MobX相关的包:
npm install --save mobx-miniprogram@4.13.2 mobx-miniprogram-bindings@1.2.1
删除目录树下的包
构建npm的包
(2).创建MobX的Store实列
store/store.js
// 在这个js文件中,专门来常见Store的实列对象
import { action, observable } from "mobx-miniprogram"; // 引入MobX,这里的数据都不能自定义
// 抛出 Mobx
export const store = observable({
// 共享下面的变量
// (1).共享数据字段
numA:1,
numB:2,
// (2).计算属性 -》 关键字 get 表示这个计算属性是只能 读取的。
get sum(){
return this.numA+this.numB
},
// (3).actions 方法 用来修改store中的数据
updateNum1:action(function(step){ // 第一个是 自定义方法名, 第二个是 action
this.numA+=step
}),
updateNum2:action(function(step){
this.numB+=step
})
})
(3).将Store中的成员绑定到页面中
home.wxml
// 1. 导入包和实列对象
import { createStoreBindings } from 'mobx-miniprogram-bindings';
import { store } from '../../store/store';
Page({
/**
* 页面的初始数据
*/
data: {
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
// 绑定
this.storeBindings= createStoreBindings(this,{
store, // 1.实列对象
fields:['numA','numB','sum'], // 2. 我们在store.js中定义的属性
actions:['updateNum1','updateNum2'] // 3. 我们在store.js中定义的方法
})
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
// 解除绑定
this.storeBindings.destoryStoreBindings()
},
})
(4).在页面上使用Store中的成员
home.wxml
<!--pages/home/home.wxml-->
<text class="t1">首页</text>
<view>
{{numA}}+{{numB}}={{sum}}
</view>
<!-- 利用 Vant组件 并绑定处理事件且传递参数 -->
<van-button type="primary" bindtap="btnHandler" data-step="{{1}}">numA+1</van-button>
<van-button type="danger" bindtap="btnHandler" data-step="{{-1}}" >numA-1</van-button>
home.js
import { createStoreBindings } from 'mobx-miniprogram-bindings';
import { store } from '../../store/store';
btnHandler(e){
console.log(e)
this.updateNum1(e.currentTarget.dataset.step)
},
// 1. 导入包和实列对象
import { createStoreBindings } from 'mobx-miniprogram-bindings';
import { store } from '../../store/store';
Page({
/**
* 页面的初始数据
*/
data: {
count:0
},
btnHandler(e){
console.log(e)
this.updateNum1(e.currentTarget.dataset.step)
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
// 绑定
this.storeBindings= createStoreBindings(this,{
store, // 1.实列对象
fields:['numA','numB','sum'], // 2. 我们在store.js中定义的属性
actions:['updateNum1','updateNum2'] // 3. 我们在store.js中定义的方法
})
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
this.storeBindings.destoryStoreBindings()
},
})
(5).将Store 中的成员绑定到组件
我们在组件的 .js页面进行引入。
test.js
// components/test/test.js
// 第一步: 映射到本组件中
import { storeBindingsBehavior } from 'mobx-miniprogram-bindings';
// 第二步: 接受映射
import { store } from '../../store/store';
Component({
// 第三步: 通过storeBindingsBehavior来实现自动绑定
behaviors:[storeBindingsBehavior],
storeBindings:{
// 第四步: 指定要绑定的数据源Store
store,
// 第五步: 指定要绑定的字段数据
fields:{
// 格式为: numA->'绑定的数据源名'
numA:'numA', //绑定字段的第一种方式
numB:'numB', // 绑定字段的第二种方式
sum:'sum' // 绑定字段的第三种方式
},
// 第六步: 指定绑定的方法
actions:{
updateNum2:'updateNum2'
}
},
})
(6).在组件中使用Store中的成员
test.wwxml
<!--components/test/test.wxml-->
<view>
{{numA}}+{{numB}}={{sum}}
</view>
<!-- 绑定按钮并传递参数 -->
<van-button type="primary" bindtap="btnHandler2" data-step="{{1}}">numB+1</van-button>
<van-button type="primary" bindtap="btnHandler2" data-step="{{-1}}">numB-1</van-button>
组件的.js
methods: {
btnHandler2(e){
this.updateNum2(e.target.dataset.step)
}
}
(九)、分包
1.分包 -概念
(1).什么是分包
分包指的是把一个完整的小程序项目
,按照需求划分为不同的子包
,在构建时打包成不同的分包,用户在使用时按需进行加载
。
(2).分包的好处
对小程序进行分包的好处主要有以下两点:
- 可以
优化小程序首次启动的下载时间
。 - 在
多团队共同开发
时可以更好的解耦协作
。
(3).分包前项目的构成
分包前,小程序项目中所有的页面
和资源
都被打包到了一起,导致整个项目体积过大
,影响小程序首次启动的下载时间
。
(4).分包后项目的构成
分包后,小程序项目由 1个主包 + 多个分包
组成:
- 主包: 一般只包含项目的
启动页面
或TabBar页面
、以及所有分包都需要用到的一些公共资源
。 - 分包: 只包含和当前分包有关的页面和私有资源。
(5).分包的加载机制
- 在小程序启动时,默认会
下载主包
并启动主包内页面
-
- tabBar页面需要放到主包中
- 当用户进入分包内某个页面时,
客户端会把对应分包下载下来
,下载完成后再进行展示
-
- 非 tabBar页面可以按照功能的不同,划分为不同的分包之后,进行按需下载
(6).分包的体积限制
目前,小程序分包的大小有以下两个限制:
- 整个小程序所有分包大小不超过16M (主包+所有分包)
- 单个分包/主包大小不能超过2M
2.分包 - 使用分包
(1).配置方法
- 如何创建分包
app.json
1. 新增一个属性对象 subPackages -> 内嵌有几个对象就是几个分包
2. 必须要写的一个 root属性 -> 用来指向分包的根目录名
3. pages: 用来指向我们生成的文件 -> 有多少个文件,就在这个分包下有多少页面
"subPackages": [
{
"root": "pkgA",
"pages": [
"pages/cat/cat",
"pages/dog/dog"
]
},
{
"root": "pkgB",
"pages": [
"pages/apple/apple"
]
}
],
{
"usingComponents": {
"van-button": "@vant/weapp/button/index",
"my-test1":"/components/test/test"
},
"pages":[
"pages/home/home",
"pages/message/message",
"pages/contact/contact",
"pages/info/info"
],
"subPackages": [
{
"root": "pkgA",
"pages": [
"pages/cat/cat"
]
}
],
"window":{
"backgroundTextStyle":"dark",
"navigationBarBackgroundColor": "#2b4b6b",
"navigationBarTitleText": "金橘社区",
"navigationBarTextStyle":"white",
"backgroundColor": "#efefef",
"onReachBottomDistance": 100
},
"tabBar": {
"list": [
{
"pagePath": "pages/home/home",
"text": "首页",
"iconPath": "images/index.png",
"selectedIconPath": "images/index-active.png"
},
{
"pagePath": "pages/message/message",
"text": "信息",
"iconPath": "images/mail.png",
"selectedIconPath": "images/mail-active.png"
},
{
"pagePath": "pages/contact/contact",
"text": "电话",
"iconPath": "images/phone.png",
"selectedIconPath": "images/phone-active.png"
}
]
},
"sitemapLocation": "sitemap.json"
}
- 分包的别名
"subPackages": [
{
"root": "pkgA",
"name": "p1",
"pages": [
"pages/cat/cat",
"pages/dog/dog"
]
},
{
"root": "pkgB",
"name": "p2",
"pages": [
"pages/apple/apple"
]
}
],
- 如何查看分包的各自体积
(2).打包原则
- 小程序会按
subpackages
的配置进行分包,subpackages 之外的目录将被打包到主包中 - 主包也可以有自己的 pages(即最外层的 pages 字段)
- tabBar 页面必须在主包内
- 分包之间不能互相嵌套
(3).引用原则
- 主包
无法引用
分包内的私有资源 - 分包 之间
不能相互引用
私有资源 - 分包
可以引用
主包内的公共资源
3.分包 - 独立分包
(1).什么是独立分包
独立分包本质上也是分包
,只不过它比较特殊,可以独立于主包和其他分包而独立运行
。
(2).独立分包和普通分包的区别
最主要的区别: 是否依赖于主包才能运行
- 普通分包必须依赖于主包才能运行
- 独立分包可以在不下载主包的情况下独立运行。
(3).独立分包的应用场景
开发者可以按需,将某些具有一定功能独立性的页面
配置到独立分包
中。原因如下:
- 当小程序从普通的分包页面启动时,需要首先下载主包
- 而独立分包
不依赖主包
即可运行,可以很大程度上提升分包页面的启动速度
注意: 一个程序种可以有多个独立分包
(4).独立分包的配置方法
是否有indepentdent为 true 这个节点。如果有的话,就是独立分包
将分包okgB转变为 独立分包
{
"root": "pkgB",
"name": "p2",
"pages": [
"pages/apple/apple"
],
"independent": true
}
(5).引用原则
独立分包和普通分包以及主包之间,是相互隔绝
的,不能相互引用彼此的资源
!
主包无法引用独立分包
内的私有资源独立分包之间
,不能相互引用私有资源独立分包和普通分包之间
,不能相互引用私有资源- 特别注意:
独立分包中不能引用主包内的公共资源
。普通分包是可以实现引用主包内的资源。
4.分包 - 分包预下载
(1).什么是分包预下载
分包预下载指的是:在进入小程序的某个页面时,由框架自动预下载可能需要的分包
,从而提升进入后续分包页面时的启动速度。
比如 进入到 联系页面,可能要用到 cat 页面,我们就预下载 pack1 分包
(2).配置分包的预下载
预下载分包的行为,会在进入指定的页面时触发
。在 app.json 中,使用 preloadRule
节点定义分包的预下载规则
"preloadRule": {
"pages/contact/contact":{
"packages": ["pkgA"],
"network": "all"
}
},
(3).分包预下载的限制
同一个分包中的页面享有共同的预下载大小限额2M,例如:
- 当小程序进入到主页面的时候,会下载他们所对应的分包(分包预下载),他们
共同的预下载不能超过 2兆
5.案列 - 自定义 tabBar
(1).本案列主要用到的知识点
- 自定义组件
- Vant组件库
- MobX数据共享
- 组件样式隔离
- 组件数据监听
- 组件的behaviors
- Vant样式覆盖
(2).实现步骤
自定义tabBar分为3大步骤
- 配置信息 (app.json)
- 添加tabBar代码文件
- 编写tabBar代码
(3).配置信息
- 在
app.json
中的tabBar
项指定custom
字段,同时其余tabBar
相关配置也补充完整。 - 所有
tab
页的json
里需声明usingComponents
项,也可以在app.json
全局开启。
- 为了保证低版本兼容以及区分哪些页面是 tab 页,tabBar 的相关配置项需完整声明,但这些字段不会作用于自定义 tabBar 的渲染。
"tabBar": {
"custom": true,
"list": [
{
"pagePath": "pages/home/home",
"text": "首页",
"iconPath": "images/index.png",
"selectedIconPath": "images/index-active.png"
},
{
"pagePath": "pages/message/message",
"text": "信息",
"iconPath": "images/mail.png",
"selectedIconPath": "images/mail-active.png"
},
{
"pagePath": "pages/contact/contact",
"text": "电话",
"iconPath": "images/phone.png",
"selectedIconPath": "images/phone-active.png"
}
]
},
- 添加 tabBar 代码文件
在代码根目录下添加入口文件:
custom-tab-bar/index.js
custom-tab-bar/index.json
custom-tab-bar/index.wxml
custom-tab-bar/index.wxss
(4).添加tabBar代码文件
- 引入Vant做效果装饰
app.json
引用的是单个组件
"usingComponents": {
"van-tabbar": "@vant/weapp/tabbar/index",
"van-tabbar-item": "@vant/weapp/tabbar-item/index"
}
- 自定义选中图标和未选中图标
<van-tabbar-item info="3">
<image
slot="icon"
src="/images/index.png" 选中的路径图片
mode="aspectFit"
style="width: 30px; height: 18px;"
/>
<image
slot="icon-active"
src="/images/index-active.png" 未选中的路径图片
mode="aspectFit"
style="width: 30px; height: 18px;"
/>
首页
</van-tabbar-item>
<!--custom-tab-bar/index.wxml-->
<van-tabbar active="{{ active }}" bind:change="onChange">
<van-tabbar-item info="3">
<image
slot="icon"
src="/images/index.png"
mode="aspectFit"
style="width: 30px; height: 18px;"
/>
<image
slot="icon-active"
src="/images/index-active.png"
mode="aspectFit"
style="width: 30px; height: 18px;"
/>
首页
</van-tabbar-item>
<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>
- 循环遍历自定义图标
赋值app.json的tabBar的list数组到index.js的data区域中
对象其实也是 “” 引用的,只不过在data区域可以省略
"list": [
{
"pagePath": "pages/home/home",
"text": "首页",
"iconPath": "/images/index.png",
"selectedIconPath": "/images/index-active.png"
},
{
"pagePath": "pages/message/message",
"text": "信息",
"iconPath": "/images/mail.png",
"selectedIconPath": "/images/mail-active.png"
},
{
"pagePath": "pages/contact/contact",
"text": "电话",
"iconPath": "/images/phone.png",
"selectedIconPath": "/images/phone-active.png"
}
]
index.wxml
<!--custom-tab-bar/index.wxml-->
<van-tabbar active="{{ active }}" bind:change="onChange">
<van-tabbar-item wx:for="{{list}}" wx:key="index">
<image
slot="icon"
src="{{item.iconPath}}"
mode="aspectFit"
style="width: 30px; height: 18px;"
/>
<image
slot="icon-active"
src="{{item.selectedIconPath}}"
mode="aspectFit"
style="width: 30px; height: 18px;"
/>
{{item.text}}
</van-tabbar-item>
</van-tabbar>
(5).渲染tabBar上的数字徽标
index.wxml
我们只需要在Vant的组件上添加 一个 info="x" 即可
<!--custom-tab-bar/index.wxml-->
<van-tabbar active="{{ active }}" bind:change="onChange">
<van-tabbar-item wx:for="{{list}}" wx:key="index" info="2">
<image
slot="icon"
src="{{item.iconPath}}"
mode="aspectFit"
style="width: 30px; height: 18px;"
/>
<image
slot="icon-active"
src="{{item.selectedIconPath}}"
mode="aspectFit"
style="width: 30px; height: 18px;"
/>
{{item.text}}
</van-tabbar-item>
</van-tabbar>
- 如何让徽标不超过tabBar的指定框
第一步:在index.js中添加属性
"options":{
styleIsolation:'shared'
},
// custom-tab-bar/index.js
Component({
"options":{
styleIsolation:'shared'
},
/**
* 组件的属性列表
*/
properties: {
},
/**
* 组件的初始数据
*/
data: {
active: 0,
list: [
{
"pagePath": "pages/home/home",
"text": "首页",
"iconPath": "/images/index.png",
"selectedIconPath": "/images/index-active.png"
},
{
"pagePath": "pages/message/message",
"text": "信息",
"iconPath": "/images/mail.png",
"selectedIconPath": "/images/mail-active.png"
},
{
"pagePath": "pages/contact/contact",
"text": "电话",
"iconPath": "/images/phone.png",
"selectedIconPath": "/images/phone-active.png"
}
]
},
/**
* 组件的方法列表
*/
methods: {
onChange(event) {
// event.detail 的值为当前选中项的索引
this.setData({ active: event.detail });
},
}
})
第二步:在index.wxss写如下配置
/* custom-tab-bar/index.wxss */
.van-tabbar-item{
--tabbar-item-margin-bottom:0;
}
- 动态监听数字的变化
向用Mobx将数据传递过来
index.js
import { storeBindingsBehavior } from 'mobx-miniprogram-bindings'
import { store } from "../store/store"
behaviors:[storeBindingsBehavior],
storeBindings:{
// 第四步: 指定要绑定的数据源Store
store,
// 第五步: 指定要绑定的字段数据
fields:{
sum:'sum' // 绑定字段的第三种方式
},
// 第六步: 指定绑定的方法
actions:{
}
},
observers:{
'sum':function(newSum){
console.log(newSum)
this.setData({
// 1这里我们不用写 this.data 直接写对象名即可。因为已经帮我们自动填充了
'list[1].info':newSum
})
}
},
(5).实现tabBar页面的切换
index.js
methods: {
onChange(event) {
// event.detail 的值为当前选中项的索引
this.setData({ active: event.detail });
wx.switchTab({
url: this.data.list[event.detail].pagePath,
})
},
}
- 解决光标不一致的情况
store.js
共享数据和方法
// 在这个js文件中,专门来常见Store的实列对象
import { action, observable } from 'mobx-miniprogram'; // 引入MobX
// 抛出 Mobx
export const store = observable({
// 共享下面的变量
activeTabBrIndex:0,
// (1).共享数据字段
numA:1,
numB:2,
// (2).计算属性 -》 关键字 get 表示这个计算属性是只能 读取的。
get sum(){
return this.numA+this.numB
},
// (3).actions 方法 用来修改store中的数据
updateNum1:action(function(step){ // 第一个是 自定义方法名, 第二个是 action
this.numA+=step
}),
updateNum2:action(function(step){
this.numB+=step
}),
updateActiveTabBrIndex:action(function(indx){
this.activeTabBrIndex=indx
})
})
index.js
// custom-tab-bar/index.js
import { storeBindingsBehavior } from 'mobx-miniprogram-bindings'
import { store } from "../store/store"
Component({
behaviors:[storeBindingsBehavior],
storeBindings:{
// 第四步: 指定要绑定的数据源Store
store,
// 第五步: 指定要绑定的字段数据
fields:{
sum:'sum', // 绑定字段的第三种方式
active1:'activeTabBrIndex'
},
// 第六步: 指定绑定的方法
actions:{
updateActive1:'updateActiveTabBrIndex'
}
},
observers:{
'sum':function(newSum){
console.log(newSum)
this.setData({
// 1这里我们不用写 this.data 直接写对象名即可。因为已经帮我们自动填充了
'list[1].info':newSum
})
}
},
"options":{
styleIsolation:'shared'
},
data: {
active: 0,
list: [
{
"pagePath": "/pages/home/home",
"text": "首页",
"iconPath": "/images/index.png",
"selectedIconPath": "/images/index-active.png"
},
{
"pagePath": "/pages/message/message",
"text": "信息",
"iconPath": "/images/mail.png",
"selectedIconPath": "/images/mail-active.png",
info:2
},
{
"pagePath": "/pages/contact/contact",
"text": "电话",
"iconPath": "/images/phone.png",
"selectedIconPath": "/images/phone-active.png"
}
]
},
methods: {
onChange(event) {
// event.detail 的值为当前选中项的索引
this.setData({ active: event.detail });
this.updateActive1(event.detail)
wx.switchTab({
url: this.data.list[event.detail].pagePath,
})
},
}
})
index.wxml
<!--custom-tab-bar/index.wxml-->
<van-tabbar active="{{ active1 }}" bind:change="onChange">
<!-- 假如说 item.info 存在的话,那么输出数字徽标 否则不输出 -->
<van-tabbar-item wx:for="{{list}}" wx:key="index" info="{{item.info ? item.info : ''}}">
<image
slot="icon"
src="{{item.iconPath}}"
mode="aspectFit"
style="width: 30px; height: 18px;"
/>
<image
slot="icon-active"
src="{{item.selectedIconPath}}"
mode="aspectFit"
style="width: 30px; height: 18px;"
/>
{{item.text}}
</van-tabbar-item>
</van-tabbar>
(7).设置选中文本框的颜色
active-color="#13A7A0"