118.【微信小程序 - 02】

news2024/11/27 0:25:36

微信小程序-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) 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。"

  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){  // 第一个是 自定义方法名, 第二个是 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).分包的好处

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

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

在这里插入图片描述

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

在这里插入图片描述

  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:{
    // 第四步: 指定要绑定的数据源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,
      })
    },
  }

在这里插入图片描述

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

在这里插入图片描述
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"

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/608137.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【2023】Redis哨兵模式集群

目录 &#x1f3b6; 哨兵模式&#x1f3b6; 搭建哨兵模式集群&#x1f3b6; 搭建一主二从复制集群&#x1f3b6; 创建哨兵节点 &#x1f3b6; 哨兵节点的其他配置&#x1f3b6; 哨兵模式下故障自动恢复效果&#x1f3b6; 通过日志查看故障恢复过程 &#x1f3b6; 哨兵模式 一般…

华为OD机试真题 Java 实现【获取字符串中连续出现次数第k多的字母的次数】【2023Q1 100分】,附详细解题思路

一、题目描述 给定一个字符串&#xff0c;只包含大写字母&#xff0c;求在包含同一字母的子串中&#xff0c;长度第 k 长的子串的长度&#xff0c;相同字母只取最长的那个子串。 二、输入描述 第一行有一个子串(1<长度<100)&#xff0c;只包含大写字母&#xff1b;第二…

Zinx框架学习 - 多路由实现

Zinx - V0.6 多路由实现 之前在已经给Zinx配置了路由模式&#xff0c;但是之前的Zinx只能绑定一个路由的处理业务方法显然这是无法满足基本的服务器需求&#xff0c;需要给Zinx添加多路由的方案查看之前的Server定义&#xff0c;路由Router只有一个&#xff0c;当我们想要再添…

七个很好的 Python 工具,让你的生活更轻松

有一句谚语“你不必重新发明轮子”。工具就是最好的例子。它可以帮助您以简单的方式实现复杂且耗时的功能。在我看来&#xff0c;为了提高生产力和效率&#xff0c;我们需要使用一些可用的最佳工具。在这里&#xff0c;我整理了 7 个工具&#xff0c;可以帮助您完成开发之旅。 …

【网络】TCP通讯(三次握手、四次挥手;滑动窗口;TCP状态转换;端口复用;TCP心跳检测机制)

前言&#xff1a;建议看着图片&#xff0c;根据文字描述走一遍TCP通讯过程&#xff0c;加深理解。 目录 TCP通信时序&#xff1a; 1&#xff09;建立连接&#xff08;三次握手&#xff09;的过程&#xff1a; 2&#xff09;数据传输的过程&#xff1a; 3&#xff09;关闭连…

java的IP组播

文章目录 1. 简介2. 组播地址和组3. 客户端和服务器4. 路由器和路由5. 使用组播Socket6. 构造函数7. 与组播组通信8. 案例实战 1. 简介 前面介绍的Socket都是单播Socket&#xff0c;它们提供点对点的通信。单播Socket在两个明确的端点之间创建一个连接&#xff0c;有一个发送方…

LNMP平台搭建

文章目录 安装 Nginx 服务安装 MySQL 服务安装配置 PHP 解析环境 安装 Nginx 服务 systemctl stop firewalld systemctl disable firewalld setenforce 0安装依赖包 yum -y install pcre-devel zlib-devel gcc gcc-c make创建运行用户 useradd -M -s /sbin/nologin nginx编译…

ArduPilot之H743+BMI270x2+First Normal Takeoff

ArduPilot之H743BMI270x2First Normal Takeoff 1. 源由2. 正常起飞3. 问题汇总3.1 机架构型3.2 IMU对齐3.3 接收机3.4 GPS3.5 VTX3.6 电调3.7 PID 4. 总结5. 参考资料6. 附录6.1 补充AcroTrainer视频6.2 补充Acro视频 1. 源由 鉴于目前该飞控板子在ArduPilot开源社区尚未得到官…

Photoshop 批量照片转格式

Photoshop 批量照片转格式 文章目录 Photoshop 批量照片转格式前言一、打开Photoshop软件二、打开图像处理器三、参数设置四、运行 前言 在工作和学习中&#xff0c;我们可能会遇到需要处理多张图片、更改多张图片格式的情况&#xff0c;如果一张一张的进行处理是很麻烦浪费时…

一步一步从功能测试到测试开发,我这一路的坎坷谁能懂?

读者提问&#xff1a; 测试开发工程师到底是测试&#xff0c;还是开发 &#xff1f; 鱼鱼回答&#xff1a; 既是测试&#xff0c;也是开发。 首先&#xff0c;测试开发是测试工程师&#xff0c;他们是服务于业务测试同学的&#xff0c;目标是解决业务测试工程师的具体问题。…

基于flask的web应用开发——接受post请求

目录 0. 前言1. 了解post方法2. 在flask中实现3. 具体讲解 0. 前言 操作系统&#xff1a;Windows10 家庭版 开发环境&#xff1a;Pycahrm Comunity 2022.3 Python解释器版本&#xff1a;Python3.8 第三方库&#xff1a;flask 1. 了解post方法 POST是HTTP协议定义的一种请…

尚硅谷JUC极速版笔记

尚硅谷JUC极速版笔记 1、JUC概述1.1 进程和线程1.2 线程的状态&#xff08;6个&#xff09;1.3 wait和sleep1.4 并发与并行1.5 管程&#xff08;锁&#xff09;1.6 用户线程和守护线程 2、Lock接口2.1 复习synchronized&#xff08;java内置同步锁&#xff09;2.2 什么是Lock接…

03使用IDEA快速开发一个WEB应用的具体流程

使用集成开发环境实现web开发 集成开发工具很多&#xff0c;其中目前使用比较多的是IntelliJ IDEA和Eclipse IntelliJ IDEA(居多): JetBrain公司开发的收费软件, IDEA在提示功能方面要强于Eclipse使用起来更加智能更好用Eclipse(较少):Eclipse是IBM团队开发的, Eclipse寓意是…

ChatGPT 国内镜像网站独家汇总:发现最优秀的人工智能对话体验!

欢迎来到我们的 ChatGPT 镜像网站汇总博客&#xff01;在这个令人激动的人工智能时代&#xff0c;ChatGPT 作为一款顶尖的语言模型&#xff0c;已经引起了全球范围内的热议。但是&#xff0c;您是否曾经为了找到最佳的 ChatGPT 使用体验而苦苦搜寻&#xff1f;别担心&#xff0…

电商业务逻辑总结

一、后台模块:商品管理 1. 基本概念 ① spu: 标准化产品单元 不是一件具体的商品 eg iphone14 ② sku: 库存量单元 指的就是一件具体的商品 eg iphone14 128G 蓝色 ③ 销售属性 出现了商品详情页右侧的商品属性信息 ④ 平台属性 出现了商品详情页下…

vue 实现微信扫码登录的方法

一、准备工作&#xff1a; 1.微信公众号&#xff0c;扫码登录 2.域名&#xff0c;也就是域名解析&#xff08;public_domain&#xff09; 3.微信登录验证 4.配置微信扫码登录页面的代码&#xff0c;有了上面的准备工作&#xff0c;下面就可以开始编码了。 二、开发环境&#xf…

pinia的用法,一篇文章教你搞懂vuex的继任者pinia

一&#xff1a;pinia是什么&#xff1f; Pinia 是一个轻量级的、易于使用的 Vue.js 状态管理库。它是 Vuex 的一个替代方案&#xff0c;专为 Vue 3 设计&#xff0c;提供了更简单的 API 和更好的 TypeScript 支持。在你提供的代码中&#xff0c;Pinia 被用于管理应用程序的状态…

VAO、VBO、EBO简介

1.顶点缓冲对象(Vertex Buffer Objects, VBO) 顶点缓冲对象&#xff08;VBO&#xff09;的作用就是管理这个在GPU上创建的显存。使用这些缓冲对象的好处是我们可以一次性的发送一大批数据到显卡上&#xff0c;而不是每个顶点发送一次。从CPU把数据发送到显卡相对较慢&#xff…

java.security.MessageDigest的用法

java.security.MessageDigest MessageDigest的含义 message含义是:消息,信息 digest的含义是 digest 必应词典 n.摘要&#xff1b;文摘&#xff1b;概要&#xff1b;汇编 v.消化&#xff1b;领会&#xff1b;领悟&#xff1b;理解 海词 n. 摘要 vt. 消化&#xff1b;理解 vi…

进制转换(及规律)

Java变量命名规则和前端一样 约束 接口使用大驼峰 变量方法小托福 常量全大写 数值类型的 整型 byte a 1 所占空间1字节&#xff08;-128-127&#xff09; short a 1 所占空间2字节&#xff08;-32768-32767&#xff09;2^15-2^15-1 int a 1 所占空间4…