118.【微信小程序 - 02】

微信小程序-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. 注意:为了保证目录结构的清晰,建议把不同的组件,存放到单独目录中。

118.【微信小程序 - 02】_第1张图片

(2).引用组件(全局和局部)

组件的引用方式分为: "局部引用"和 “全局引用”,顾名思义:

  • 局部引用: 组件只能在当前被引用的页面内使用
  • 全局引用: 组件可以在每个小程序中使用

(3).局部引用组件

页面的.json配置文件中引用组件的方式,叫做"局部引用"。

home.wxss
引用组件的操作:

{
  "usingComponents": {
    "my-test1":"/components/test/test"
  }
}

home.wxml
使用组件的操作


<text>首页text>

<my-test1>my-test1>

其他页面并不会展示这个组件的信息
在这里插入图片描述

(4).全局引用组件

我们只需在app.json的位置出,与window平级编写以下配置即可

  "usingComponents": {
    "my-test1":"/components/test/test"
  },

118.【微信小程序 - 02】_第2张图片

(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、属性、标签选择器
118.【微信小程序 - 02】_第3张图片

(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


<text>components/test/test.wxmltext>
<view>
  <text>{{count}}text>
view>

组件.js test.js

// components/test/test.js
Component({
  // 隔离性
  options:{
    styleIsolation:'isolated'
  },
  /**
   * 组件的属性列表
   */
  properties: {

  },

  /**
   * 组件的初始数据
   */
  data: {
    count:0
  },

  /**
   * 组件的方法列表
   */
  methods: {

  }
})

118.【微信小程序 - 02】_第4张图片

(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


<text>components/test/test.wxmltext>
<view>
  <text>{{count}}text>
view>

<button type="primary" bindtap="addCount">按我+1button>

118.【微信小程序 - 02】_第5张图片

(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


<text class="t1">首页text>

<my-test1 max="4">my-test1>

118.【微信小程序 - 02】_第6张图片

(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,
        })
      }
  }
})

118.【微信小程序 - 02】_第7张图片

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


<view>
  {{n1}}+{{n2}}={{sum}}
view>

<button bindtap="addN1">n1+1button>
<button bindtap="addN2">n2+1button>

118.【微信小程序 - 02】_第8张图片

(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



<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">Rbutton>
<button type="primary" size="mini" bindtap="changeG">Gbutton>
<button type="warn" size="mini" bindtap="changeB">Bbutton>
view>

118.【微信小程序 - 02】_第9张图片

(5).监听对象中所有属性的变化

如果某个对象中需要被监听的属性太多,为了方便,可以使用通配符 ** 来监听对象中的所有属性的变化:
我们在使用欸都时候,需要用到通配符和反引号

  observers:{
    'rgb.**':function(obj){
        this.setData({
            fullColor:`${obj.r},${obj.g},${obj.b}`
        })
    }
  },

118.【微信小程序 - 02】_第10张图片

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('所有的数据初始化完毕')
    }
  },

118.【微信小程序 - 02】_第11张图片

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('所有的数据初始化完毕')
    }
  }
})

118.【微信小程序 - 02】_第12张图片

(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)
    }
  },

118.【微信小程序 - 02】_第13张图片

8.自定义组件 - 插槽

(1).什么是插槽

再打自定义组件的wxml结构中,可以提供一个< slot>节点(插槽),用于承载组件使用者提供的wxml结构

(2).使用单个插槽

在小程序中,默认每个自定义组件中只允许使用一个 < slot>进行占位,这种个数上的限制叫做单个插槽。

test4.js


<view>
  <view>
      这里是组件的内部结构
  view>
  
  <slot>slot>
view>

home.wxml


<text class="t1">首页text>

<my-test4>
    <view>
      这是通过插槽填充的数据
    view>
my-test4>

118.【微信小程序 - 02】_第14张图片

(3).启用多个插槽

在小程序的自定义组件中,需要使用多 < slot> 插槽时,可以在组件的.js文件中。通过以下的方式进行启用,默认的是一个插槽:
test4.js

// components/test4/test4.js
Component({
  options:{
    multipleSlots:true
  }
})

test4.wxml
用name取别名


<view>
  <slot name="before">slot>
  <view>
      这里是组件的内部结构
  view>
  
  <slot name="after">slot>
view>

home.wxml
通过slot属性进行绑定


<text class="t1">首页text>

<my-test4>
    <view slot="before">
      这是通过插槽填充的数据
    view>
my-test4>

118.【微信小程序 - 02】_第15张图片

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


<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


<text>父组件传递过来的数据为 : {{count}}text>

118.【微信小程序 - 02】_第16张图片

  1. 儿子调用自增的函数

test5.wxml


<text>父组件传递过来的数据为 : {{count}}text>

<button type="primary" bindtap="addCount">点我+1button>

test5.js

// components/test5/test5.js
Component({
  /**
   * 组件的属性列表
   */
  properties: {
    // 注册-> 第一个是注册的变量名,第二个是注册的变量类型
      count: Number
  },

  /**
   * 组件的初始数据
   */
  data: {

  },

  /**
   * 组件的方法列表
   */
  methods: {
    addCount(){
      console.log(this)
      this.setData({
        count:this.properties.count+1
      }) 
    }
  }
})

118.【微信小程序 - 02】_第17张图片

(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


<text class="t1">首页text>

<view>
  父组件中Count的值为: {{count}}
view>

<view>
  ---------------
view>

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

118.【微信小程序 - 02】_第18张图片

(4).获取组件实列 (父组件获取子组件实列)

可在父组件里调用 this.selectComponent(“id或class选择器”),获取子组件的实列对象,从而直接访问子组件的任意数据和方法。调用时需要传入一个选择器。
home.wxml


<text class="t1">首页text>

<view>
  父组件中Count的值为: {{count}}
view>

<view>
  ---------------
view>

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

118.【微信小程序 - 02】_第19张图片

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语法进行获取数据


<text>父组件传递过来的数据为 : {{count}}text>

<view>
  通过behavior获取的数据: {{username}}
view>

<button type="primary" bindtap="addCount">点我+1button>

(七)、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

118.【微信小程序 - 02】_第20张图片

(2).安装 Vant 组件库

在小程序项目中,安装Vant组件库主要分为如下3步:
初始化项目
118.【微信小程序 - 02】_第21张图片

npm init -y

118.【微信小程序 - 02】_第22张图片

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

118.【微信小程序 - 02】_第23张图片

  1. 构建npm包

118.【微信小程序 - 02】_第24张图片
新版本不用去本地设置里面勾选了
118.【微信小程序 - 02】_第25张图片
118.【微信小程序 - 02】_第26张图片

  1. 修改app.json

118.【微信小程序 - 02】_第27张图片

(3).使用Vant 组件

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

  1. 在app.json这个文件中写

home.json

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

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>

118.【微信小程序 - 02】_第28张图片

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

118.【微信小程序 - 02】_第29张图片

  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


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

源码118.【微信小程序 - 02】_第30张图片
根节点118.【微信小程序 - 02】_第31张图片
118.【微信小程序 - 02】_第32张图片

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 [email protected]

118.【微信小程序 - 02】_第33张图片
记住: 我们每次在微信小程序安装一个包,我们不能够立马进行使用,我们需要重新构建npm。
第一步: 删除包
118.【微信小程序 - 02】_第34张图片
第二步 重新构建
118.【微信小程序 - 02】_第35张图片
第三步: 成功之后
118.【微信小程序 - 02】_第36张图片

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

118.【微信小程序 - 02】_第37张图片

  1. 在home.wxml

hoem.xml 绑定方法


<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)
  },
})

不去掉关键字
118.【微信小程序 - 02】_第38张图片
去掉关键字
118.【微信小程序 - 02】_第39张图片

(八)、全局数据共享

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 [email protected] [email protected]

118.【微信小程序 - 02】_第40张图片
删除目录树下的包
118.【微信小程序 - 02】_第41张图片
构建npm的包
118.【微信小程序 - 02】_第42张图片

(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


<text class="t1">首页text>

<view>
  {{numA}}+{{numB}}={{sum}}
view>

<van-button type="primary" bindtap="btnHandler" data-step="{{1}}">numA+1van-button>
<van-button type="danger" bindtap="btnHandler" data-step="{{-1}}" >numA-1van-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


<view>
  {{numA}}+{{numB}}={{sum}}
view>

<van-button type="primary" bindtap="btnHandler2" data-step="{{1}}">numB+1van-button>
<van-button type="primary" bindtap="btnHandler2" data-step="{{-1}}">numB-1van-button>

组件的.js

  methods: {
    btnHandler2(e){
      this.updateNum2(e.target.dataset.step)
    }
  }

118.【微信小程序 - 02】_第43张图片

(九)、分包

1.分包 -概念

(1).什么是分包

分包指的是把一个完整的小程序项目,按照需求划分为不同的子包,在构建时打包成不同的分包,用户在使用时按需进行加载

(2).分包的好处

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

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

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

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

118.【微信小程序 - 02】_第44张图片

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

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

  1. 主包: 一般只包含项目的启动页面TabBar页面、以及所有分包都需要用到的一些公共资源
  2. 分包: 只包含和当前分包有关的页面和私有资源。
    118.【微信小程序 - 02】_第45张图片

(5).分包的加载机制

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

(6).分包的体积限制

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

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

2.分包 - 使用分包

(1).配置方法

118.【微信小程序 - 02】_第46张图片

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

118.【微信小程序 - 02】_第47张图片

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

118.【微信小程序 - 02】_第48张图片

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

118.【微信小程序 - 02】_第49张图片

(2).打包原则

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

(3).引用原则

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

3.分包 - 独立分包

(1).什么是独立分包

独立分包本质上也是分包,只不过它比较特殊,可以独立于主包和其他分包而独立运行
118.【微信小程序 - 02】_第50张图片

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

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

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

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

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

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

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

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

是否有indepentdent为 true 这个节点。如果有的话,就是独立分包
118.【微信小程序 - 02】_第51张图片
将分包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"
      }
  },

118.【微信小程序 - 02】_第52张图片
118.【微信小程序 - 02】_第53张图片

(3).分包预下载的限制

同一个分包中的页面享有共同的预下载大小限额2M,例如:

  • 当小程序进入到主页面的时候,会下载他们所对应的分包(分包预下载),他们共同的预下载不能超过 2兆

118.【微信小程序 - 02】_第54张图片

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

在这里插入图片描述
118.【微信小程序 - 02】_第55张图片

(4).添加tabBar代码文件

  1. 引入Vant做效果装饰

app.json
引用的是单个组件

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

118.【微信小程序 - 02】_第56张图片

  1. 自定义选中图标和未选中图标
  <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 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>

118.【微信小程序 - 02】_第57张图片

  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



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

118.【微信小程序 - 02】_第58张图片

(5).渲染tabBar上的数字徽标

index.wxml

我们只需要在Vant的组件上添加 一个  info="x" 即可


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

118.【微信小程序 - 02】_第59张图片

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

118.【微信小程序 - 02】_第60张图片

  1. 动态监听数字的变化

向用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
      })
    }
  },

118.【微信小程序 - 02】_第61张图片

(5).实现tabBar页面的切换

118.【微信小程序 - 02】_第62张图片
index.js

  methods: {
    onChange(event) {
      // event.detail 的值为当前选中项的索引
      this.setData({ active: event.detail });
      wx.switchTab({
        url: this.data.list[event.detail].pagePath,
      })
    },
  }

118.【微信小程序 - 02】_第63张图片

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

118.【微信小程序 - 02】_第64张图片
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,
      })
    },
  }
})

118.【微信小程序 - 02】_第65张图片
index.wxml



<van-tabbar active="{{ active1 }}" 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: 30px; height: 18px;"
    />
    <image
      slot="icon-active"
      src="{{item.selectedIconPath}}"
      mode="aspectFit"
      style="width: 30px; height: 18px;"
    />
   {{item.text}}
  van-tabbar-item>
van-tabbar>

118.【微信小程序 - 02】_第66张图片
118.【微信小程序 - 02】_第67张图片

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

active-color="#13A7A0"

118.【微信小程序 - 02】_第68张图片

你可能感兴趣的:(微信小程序,小程序,前端)