微信小程序-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).创建自定义组件

  1. 在项目的根目录中,鼠标右键,创建compoents->test文件夹。
  2. 在新建的components->test文件夹上,鼠标右键,点击"新建Component"
  3. 键入组件的名称之后回车,会自动生成组件对应的4个文件,后缀分别为 .js .json .wxml .wxss。
  4. 注意:为了保证目录结构的清晰,建议把不同的组件,存放到单独目录中。

(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).全局引用和局部引用的建议

  1. 多个页面需要使用->全局
  2. 单个页面需要使用->局部

(6).组件和页面的区别

从表面来看,组件和页面都是由. js 、.json、.wxml和.wxss着四个文件组成的。但是组件和页面的.js与.json文件明显不同。

  1. 组件的.json文件中需要声明:"component:true"属性。
  2. 组件的.js文件中调用的是 Component()函数不是Page()
  3. 组件的事件处理函数需要定义到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) returnthis.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) returnthis.setData({'rgb.r':this.data.rgb.r+10})},changeG(){if(this.data.rgb.g>255) returnthis.setData({'rgb.g':this.data.rgb.g+10})},changeB(){if(this.data.rgb.b>255) returnconsole.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。"

  1. 组件实列刚被创建好的时候,created生命周期函数会被触发
    • 此时还不能调用 setData
    • 通常在这个生命周期函数中,只应该用于给组件的this添加一些自定义的属性字段。
  1. 组件完全初始化完毕、进入页面节点树后,attached生命周期函数才会触发
    • 此时,this.data已被初始化完毕
    • 这个生命周期很有用,绝大多数初始化的工作可以在这个时机进行(比如: 请求获取初始化的数据)
  1. 在组件离开页面节点树后,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种方式

  1. 属性绑定

    • 用于父组件向子组件的指定属性设置数据,仅能设置JSON兼容的数据
  1. 事件绑定

    • 用于子组件向父组件传递数据,可以传递任意数据
  1. 获取组件实列
    • 父组件还可以通过 this.selectComponent()获取组件实列
    • 这样就可以直接访问子组件的任意数据和方法

(2).属性绑定 (父亲传递给儿子)

属性绑定用于实现父向子传值,而且只能传递普通类型的数据,无法将方法传递给子组件。

  1. 父亲组件
// 父组件的 data 节点
data:{count:0
}// 父组件的wxml结构  count="{{count}}"<my-test3 count="{{count}}"></my-test3>
<view>{{count}}</view>
  1. 子组件

我们子组件在properties节点种声明对应的属性并使用

// 子组件的 properties 节点
properties:{count:Number
}
// 子组件的wxml结构
<text>子组件->{{count}}</text>
  1. 父亲传递函数

home.wxml

<!--pages/home/home.wxml-->
<text class="t1">首页</text><view>父组件中Count的值为: {{count}}
</view><view>---------------
</view>
//  传递函数
<my-test5 count="{{count}}"></my-test5>
  1. 儿子组件接受参数

tes5t.js

// components/test5/test5.js
Component({/*** 组件的属性列表*/properties: {// 注册-> 第一个是注册的变量名,第二个是注册的变量类型count: Number},/*** 组件的初始数据*/data: {},/*** 组件的方法列表*/methods: {}
})
  1. 儿子组件输出传递过来的组件

test5.wxml

<!--components/test5/test5.wxml-->
<text>父组件传递过来的数据为 : {{count}}</text>

  1. 儿子调用自增的函数

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获取到子组件传递过来的数据
  1. 父组件定义一个函数

home.js

Page({syncCount(){console.log('syncCount')},/*** 页面的初始数据*/data: {count:0},
})
  1. 父组件将定义的方法传递给子组件

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>
  1. 子组件绑定触发事件

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})}}
})
  1. 父组件进行同步接受数据

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个限制:

  1. 不支持依赖于Node.js内置库的包
  2. 不支持依赖于浏览器内置对象的包
  3. 不支持依赖于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

  1. 通过 npm 安装 (建议指定版本为 @1.3.3)
npm i @vant/weapp@1.3.3 -S --production

  1. 构建npm包


新版本不用去本地设置里面勾选了

  1. 修改app.json

(3).使用Vant 组件

安装完 Vant 组件库之后,可以在app.jsonusingComponents节点中引入需要的组件,即可在wxml中直接使用组件。

  1. 在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).定制全局主题样式

  1. 介绍全局主题样式

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);

  1. 定制全局主题样式

在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 化

  1. 第一步在 app.js中引入

app.js
在小程序入口文件中(app.js),只需调用一次promisifyAll()方法.即可实现异步 API 的promise化。

// app.js
import {promisifyAll} from 'miniprogram-api-promise'const wxp=wx.p={}promisifyAll(wx,wxp)

  1. 在home.wxml

hoem.xml 绑定方法

<!--pages/home/home.wxml-->
<text class="t1">首页</text>
<van-button type="primary" bindtap="getinfo">默认按钮</van-button>
  1. 在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){  // 第一个是 自定义方法名, 第二个是 actionthis.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:{// 第四步: 指定要绑定的数据源Storestore,  // 第五步: 指定要绑定的字段数据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).分包的好处

对小程序进行分包的好处主要有以下两点:

  1. 可以优化小程序首次启动的下载时间
  2. 多团队共同开发时可以更好的解耦协作

(3).分包前项目的构成

分包前,小程序项目中所有的页面资源都被打包到了一起,导致整个项目体积过大,影响小程序首次启动的下载时间

(4).分包后项目的构成

分包后,小程序项目由 1个主包 + 多个分包 组成:

  1. 主包: 一般只包含项目的启动页面TabBar页面、以及所有分包都需要用到的一些公共资源
  2. 分包: 只包含和当前分包有关的页面和私有资源。

(5).分包的加载机制

  1. 在小程序启动时,默认会下载主包启动主包内页面
    • tabBar页面需要放到主包中
  1. 当用户进入分包内某个页面时,客户端会把对应分包下载下来,下载完成后再进行展示
    • 非 tabBar页面可以按照功能的不同,划分为不同的分包之后,进行按需下载

(6).分包的体积限制

目前,小程序分包的大小有以下两个限制:

  • 整个小程序所有分包大小不超过16M (主包+所有分包)
  • 单个分包/主包大小不能超过2M

2.分包 - 使用分包

(1).配置方法

  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"
}

  1. 分包的别名
  "subPackages": [{"root": "pkgA","name": "p1","pages": ["pages/cat/cat","pages/dog/dog"]},{"root": "pkgB","name": "p2","pages": ["pages/apple/apple"]}],

  1. 如何查看分包的各自体积

(2).打包原则

  1. 小程序会按 subpackages的配置进行分包,subpackages 之外的目录将被打包到主包中
  2. 主包也可以有自己的 pages(即最外层的 pages 字段)
  3. tabBar 页面必须在主包内
  4. 分包之间不能互相嵌套

(3).引用原则

  1. 主包 无法引用 分包内的私有资源
  2. 分包 之间不能相互引用私有资源
  3. 分包 可以引用 主包内的公共资源

3.分包 - 独立分包

(1).什么是独立分包

独立分包本质上也是分包,只不过它比较特殊,可以独立于主包和其他分包而独立运行

(2).独立分包和普通分包的区别

最主要的区别: 是否依赖于主包才能运行

  • 普通分包必须依赖于主包才能运行
  • 独立分包可以在不下载主包的情况下独立运行。

(3).独立分包的应用场景

开发者可以按需,将某些具有一定功能独立性的页面配置到独立分包中。原因如下:

  1. 当小程序从普通的分包页面启动时,需要首先下载主包
  2. 而独立分包不依赖主包即可运行,可以很大程度上提升分包页面的启动速度

注意: 一个程序种可以有多个独立分包

(4).独立分包的配置方法

是否有indepentdent为 true 这个节点。如果有的话,就是独立分包

将分包okgB转变为 独立分包

    {"root": "pkgB","name": "p2","pages": ["pages/apple/apple"],"independent": true}

(5).引用原则

独立分包和普通分包以及主包之间,是相互隔绝的,不能相互引用彼此的资源

  1. 主包无法引用独立分包内的私有资源
  2. 独立分包之间,不能相互引用私有资源
  3. 独立分包和普通分包之间,不能相互引用私有资源
  4. 特别注意:独立分包中不能引用主包内的公共资源。普通分包是可以实现引用主包内的资源。

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大步骤

  1. 配置信息 (app.json)
  2. 添加tabBar代码文件
  3. 编写tabBar代码

(3).配置信息

  • app.json 中的 tabBar 项指定 custom 字段,同时其余 tabBar 相关配置也补充完整。
  • 所有 tab 页的 json 里需声明 usingComponents 项,也可以在 app.json 全局开启。
  1. 为了保证低版本兼容以及区分哪些页面是 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"}]},
  1. 添加 tabBar 代码文件

在代码根目录下添加入口文件:

custom-tab-bar/index.js
custom-tab-bar/index.json
custom-tab-bar/index.wxml
custom-tab-bar/index.wxss


(4).添加tabBar代码文件

  1. 引入Vant做效果装饰

app.json
引用的是单个组件

"usingComponents": {"van-tabbar": "@vant/weapp/tabbar/index","van-tabbar-item": "@vant/weapp/tabbar-item/index"
}

  1. 自定义选中图标和未选中图标
  <van-tabbar-item info="3"><imageslot="icon"src="/images/index.png"  选中的路径图片mode="aspectFit"style="width: 30px; height: 18px;"/><imageslot="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"><imageslot="icon"src="/images/index.png"mode="aspectFit"style="width: 30px; height: 18px;"/><imageslot="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>

  1. 循环遍历自定义图标

赋值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"><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).渲染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"><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>

  1. 如何让徽标不超过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;
}

  1. 动态监听数字的变化

向用Mobx将数据传递过来

index.js


import { storeBindingsBehavior } from 'mobx-miniprogram-bindings'
import { store } from "../store/store"behaviors:[storeBindingsBehavior],storeBindings:{// 第四步: 指定要绑定的数据源Storestore,  // 第五步: 指定要绑定的字段数据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,})},}

  1. 解决光标不一致的情况

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){  // 第一个是 自定义方法名, 第二个是 actionthis.numA+=step}),updateNum2:action(function(step){this.numB+=step}),updateActiveTabBrIndex:action(function(indx){this.activeTabBrIndex=indx})
})


index.js

// custom-tab-bar/index.jsimport { storeBindingsBehavior } from 'mobx-miniprogram-bindings'
import { store } from "../store/store"Component({behaviors:[storeBindingsBehavior],storeBindings:{// 第四步: 指定要绑定的数据源Storestore,  // 第五步: 指定要绑定的字段数据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 : ''}}"><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>


(7).设置选中文本框的颜色

active-color="#13A7A0"

118.【微信小程序 - 02】相关推荐

  1. 微信小程序02【配置详解、生命周期-app对象使用、页面跳转详解】

    学习地址:https://www.bilibili.com/video/BV1sx411z77P 笔记01:https://blog.csdn.net/weixin_44949135/article/ ...

  2. 微信小程序 | 02.微信原生框架的目录结构

    文章目录 1.概述 2.MINA框架 3.小程序文件结构与传统的web对比 4.项目的目录结构 1.概述 javaScript代码写在js文件中 html代码(应该叫wxml?)写在wxml中 css ...

  3. 微信小程序开源Demo精选

    微信小程序开源Demo精选 原文:微信小程序开源Demo精选 1. 仿QQ应用程序(#社交 #聊天 #SNS) 地址:https://github.com/xiehui999/SmallAppForQ ...

  4. 微信小程序开源项目库集合

    awesome-github-wechat-weapp 是由OpenDigg整理并维护的微信小程序开源项目库集合.我们会定期同步OpenDigg上的项目到这里,也欢迎各位提交项目给我们. 如果收录的项 ...

  5. 「开源」一大波开源微信小程序

    一个github开源项目:各种开源微信小程序汇总.快来看看有没有你感兴趣的吧 地址:https://github.com/opendigg/awesome-github-wechat-weapp UI ...

  6. 微信小程序开源项目、UI框架、Demo整合

    微信小程序开源项目清单 有位大哥在github上放了个整合了很多优质的微信小程序开源项目库,方便移动开发人员便捷的找到自己需要的项目工具等,感兴趣的可以到GitHub上给他个star. 另外,我参照祈 ...

  7. 微信小程序开源代码汇总分享【转载】

    https://github.com/opendigg/awesome-github-wechat-weapp awesome-github-wechat-weapp 是由OpenDigg整理并维护的 ...

  8. 【微信】【汇总】微信小程序开源项目库汇总

    https://github.com/opendigg/awesome-github-wechat-weapp awesome-github-wechat-weapp 是由OpenDigg整理并维护的 ...

  9. 微信小程序_基础组件学习02

    微信小程序_基础组件学习02 swiper组件 swiper是滑块容器,也就是手机端的轮播图. swiper组件有两部分组成swiper和swiper-item. swiper-item需要放在swi ...

最新文章

  1. luogu P5142 区间方差(线段树、乘法逆元)
  2. MySQL默认配置文件位置发生改变后如何查找
  3. python画-如何用Python画各种著名数学图案 | 附图+代码
  4. “5W1H”带你来学习JavaScript
  5. python opencv cv.applyColorMap()函数(颜色映射)ColormapTypes【将Intel Realsense D435深度图的黑白图映射为彩色图】
  6. boost::mpl模块实现is_sequence相关的测试程序
  7. 实验心得_大肠杆菌原核表达实验心得(上篇)
  8. Python扩展库scipy中值滤波算法的应用
  9. The First Python man in Github
  10. DHTML3(表格动态创建,删除行/列,表格行排序,行颜色交替高亮显示)
  11. Atitit.jsou html转换纯文本 java c# php
  12. Laravel Eloquent 数据查询结果中日期的格式化
  13. 激活码和注册码有什么不同?
  14. subs php,nginx subs_filter对输出内容进行替换
  15. 明源售楼系统技术解析(一)搭建MVC3框架
  16. 阿里云香港服务器带宽太贵怎么办?香港节点全球CDN加速你值得拥有
  17. PyCharm:ModuleNotFoundError:No module named 'selenium' 解决方法
  18. Unity 计算角度和方向
  19. 全球及中国零信任远程浏览器隔离行业运营规划与应用前景分析报告2022版
  20. Mac下查找支持的字体

热门文章

  1. 108K加湿器开发方案 芯片制造 NY8A051F 单片机开发设计开发
  2. 数字孪生推动军营智慧化管理,军事化应用战场空间可视化解决方案
  3. Linux内核配置选项的说明,Linux内核配置选项翻译
  4. 2019全国数学建模大赛c题出租车机场数据(二)
  5. 读《精通正则表达式》-- 网上 js 正则基础教程没有涉及的一些知识
  6. AMD双核玩游戏死机问题解决方案
  7. 电子地图服务行业市场运营态势及发展趋势研究分析
  8. ChatGPT、低代码等技术出现会不会导致底层程序员失业
  9. php生成mobileconfig,.mobileconfig的生成与签名
  10. 绿茶GhostXP SP3纯净版系统虚拟机安装教程