您的当前位置:首页正文

微信小程序之自定义组件

2024-11-28 来源:个人技术集锦


自定义组件

1.创建组件

②在新建的 components -> test 文件夹上,鼠标右键,点击“新建 Component'

③键入组件的名称之后回车,会自动生成组件对应的 4个文件,后缀名分别为 js,json,.wxml和.wxss

2.引用组件

组件的引用方式分为“局部引用”和“全局引用

局部引用:组件只能在当前被引用的页面内使用

全局引用:组件可以在每个小程序页面中使用

3.局部引用组件

在页面的.json文件中引用组件,即为局部引用组件,该组件只能在当前被引用的页面内使用

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


<my-test></my-test>

4.全局引用组件

在app.json文件中引用组件,即为全局引用组件,该组件可以在任意页面内使用

代码同上

5.组件使用情况

倘若一个组件需要在多个页面被多次调用,则使用全面引用组件。

倘若一个组件仅在一个页面内被多次调用,则只需使用局部引用组件。

6.组件和页面的区别

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

组件的 .json 文件中需要声明"component": true 属性

组件的.js 文件中调用的是 Component()函数(页面的是Pages()函数)

组件的事件处理函数需要定义到 methods 节点中

自定义组件的样式

默认情况下,自定义组件的样式只对当前组件生效,不会影响到组件之外的Ul 结构

好处:

防止外界的样式影响组件内部的样式

防止组件的样式破坏外界的样式

 1.组件样式隔离的特点

app.wxss中的全局样式对组件无效

只有class 选择器会有样式隔离效果,id 选择器、属性选择器、标签选择器不受样式隔离的影响

建议:在组件和用组件的页面中建议使用 class 选择器而不要使用 id、属性、标签选择器

 2.修改样式隔离选项

默认情况下,自定义组件的样式隔离特性能够防止组件内外样式互相干扰的问题。但有时,我们希望在外界能够控制组件内部的样式,此时,可以通过 stylelsolation 修改组件的样式隔离选项,用法如下:

在js文件中:
Component({
  options:{
  styleIsolation:'isolated'
  })


或者在json文件中:
"styleIsolation": "isolated"

3.stylesolation的可选值

 自定义组件的数据、方法和属性

1.data数据

类似于页面,在小程序组件中,用于组件模板渲染的私有数据需要定义在data节点中。

2.methods 方法

在小程序组件中,事件处理函数和自定义方法都需要放在methods节点中,其中自定义函数需以_开头,例:

<button type="primary" bindtap="btp">+1</button>


  methods: {
    btp(){
      this.setData({
        count: this.data.count +1
      })
    this._showCount()
    },
    _showCount(){
      wx.showToast({
        title: 'count的值为:'+ this.data.count,
        icon:'none'
      })
    }
  }

3.properties属性

在小程序组件中,properties 是组件的对外属性,用来接收外界传递到组件中的数据。(在页面的.json文件中引用组件后,才能在对应的.wxml文件中使用该组件)示例代码如下:

//在.js文件中
properties: {
    // 简单的定义方式
    // max:Number
    // 完整的定义方式
  max:{
    type:Number,
    value:10
  }
  },

//在.json文件中
"usingComponents": {
    "my-test":"/components/test/test"
  }

//在该.json对应的.wxml文件中
<my-test max="10"></my-test>

4.data和properties的区别

在小程序的组件中,properties 属性和 data 数据的用法相同,它们都是可读可写的,只不过:

data 更倾向于存储组件的私有数据

properties 更倾向于存储外界传递到组件中的数据

验证方法:

methods: {
    _showInfo(){
      console.log(this.data)
      console.log(this.properties)
      console.log(this.data === this.properties)
    }
}



<button type="primary" bindtap="_showInfo">_showInfo</button>

5.使用setData修改properties的值

由于 data 数据和 properties 属性在本质上没有任何区别,因此 properties 属性的值也可以用于页面渲染或使用setData为properties 中的属性重新赋值,示例代码如下:

methods: {
btp() {
      if (this.data.count >= this.properties.max) return
      this.setData({
        count: this.data.count + 1,
        max:this.properties.max +1
      })
      console.log(this.properties.max)
      this._showCount()
    }
}

数据监听器

1.什么是数据监听器

数据监听器用于监听和响应任何属性和数据字段的变化,从而执行特定的操作。它的作用类似于 vue 中的watch 侦听器。在小程序组件中,数据监听器的基本语法格式如下:

Component({
  observers: {
    '字段A,字段B':function(字段A的新值,字段B的新值){
    //需要处理的事务
    }
  }
})

2.数据监听器的基本用法

例:使用监听器实现n1n2改变后自动改变他们的和

注意在对应的.json文件中进行引用,不然无法显示
Component({
  data: {
    n1:0,
    n2:0,
    sum:0
  },
ods: {
  btp1(){
    this.setData({
      n1:this.data.n1+1
    })
  },
  btp2(){
    this.setData({
      n2:this.data.n2+1
    })
  }
    },
  observers:{
  'n1,n2':function(n1,n2){
    this.setData({
      sum:this.data.n1 + this.data.n2
    })
  }
  }
})


<view>{{n1}} + {{n2}} = {{sum}}</view>
<button type="primary" bindtap="btp1">n1+</button>
<button type="primary" bindtap="btp2">n2+</button>

3.监听对象属性的变化

数据监听器支持监听对象的单个或多个属性的变化,示例如下:

observers:{
  '对象.属性1,对象.属性2':function(属性1的新值,属性2的新值){
  // 触发此监听器的 3 种情况:
//[为属性A赋值] 使用 setData 设置 this.data.对象.属性A 时触发
//[为属性B赋值]使用 setData 设置 this.data.对象.属性B 时触发
//[直接为对象赋值]使用 setData 设置 this.data.对象 时触发
// do something...
  }
  }

纯数据字段

1.概念

纯数据字段指的是不用于界面渲染的data字段

应用场景:例如有些情况下,某些 data 中的字段既不会展示在界面上,也不会传递给其他组件,仅仅在当前组件内部使用。带有这种特性的 data 字段适合被设置为纯数据字段。

好处:提升页面更新的性能

2.使用规则

在Component 构造器的 options 节点中,指定 pureDataPattern 为一个正则表达式,字段名符合这个正则表达式的字段将成为纯数据字段,示例代码如下:

Component({
  options: {
    //指定所有的以_开头的的数据字段为纯数据字段
    pureDataPattern: /^_/
  },
  data: {
  a:true, //普通数据字段
  _b:true //纯数据字段
  }
})

组件的生命周期

1.组件的全部生命周期函数

2.重要的生命周期函数

在小程序生命周期当中,最重要的生命周期函数有三个,分别是created、attached、detached。它们各自的特点如下:

①组件实例刚被创建好的时候,created 生命周期函数会被触发

此时还不能调用 setData

通常在这个生命周期函数中,只应该用于给组件的 this 添加一些自定义的属性字段

②在组件完全初始化完毕、进入页面节点树后,

attached 生命周期函数会被触发

此时,this.data 已被初始化完毕

这个生命周期很有用,绝大多数初始化的工作可以在这个时机进行(例如发请求获取初始数据)

③在组件离开页面节点树后, detached 生命周期函数会被触发

退出一个页面时,会触发页面内每个自定义组件的 detached 生命周期函数

此时适合做一些清理性质的工作

3.lifetimes节点

在小程序组件中,生命周期函数可以直接定义在 Component 构造器的第一级参数中,可以在 lifetimes 字段内进行声明 (这是推荐的方式,其优先级最高)。示例代码如下:

lifetimes:{
      created(){
        console.log('created')
      },
      attached(){
        console.log('attached')
      }
    }

组件所在页面的生命周期

1.什么是组件所在页面的生命周期

有时,自定义组件的行为依赖于页面状态的变化,此时就需要用到组件所在页面的生命周期。

例如:每当触发页面的 show 生命周期函数的时候,我们希望能够重新生成一个随机的 RGB 颜色值

在自定义组件中,组件所在页面的生命周期函数有如下3个,分别是:

2.pageLifetimes节点

组件所在页面的生命周期函数,需定义在pageLifetimes节点下,例如:

pageLifetimes:{
  show:function(){
    console.log('show')
  },
  hide(){
    console.log('hide')
  },
  resize(){
    console.log('resize')
  }
  }

 3.在启动时执行一个赋随机值的方法

methods: {
    _randomNumber(){
      this.setData({
        _rgb:{
        r:Math.floor(Math.random()*256),
        g:Math.floor(Math.random()*256),
        b:Math.floor(Math.random()*256)
        }
      })
    }
},
pageLifetimes:{
  show:function(){
    this._randomNumber()
    console.log(this.data._rgb)
    
  }}

数据监听器-案例

实现在页面上显示一个颜色,该颜色由r,g,b三个元素组成RGB颜色,同时定义一个三个按键课时其对应的元素每次+5但不超过上限(256),并在页面初始化时随机赋予一个随机值显现出来

<view style="background-color: rgb({{fullcolor}});" class="colorBox">颜色值:{{fullcolor}}</view>
<button size="mini" bindtap="changeR" type="default">R</button>
<button size="mini" bindtap="changeG" type="primary">G</button>
<button size="mini" bindtap="changeB" type="warn">B</button>


.colorBox {
  line-height: 200rpx;
  font-size: 24rpx;
  color: white;
  text-shadow: 0rpx 0rpx 2rpx black;
  text-align: center;
} 


Component({
  options: {
    pureDataPattern: /^_/
  },
  /**
   * 组件的属性列表
   */
  properties: {

  },

  /**
   * 组件的初始数据
   */
  data: {
    _rgb:{
   r:0,
   g:0,
   b:0
  },
   fullcolor:'0,0,0'
  },

  /**
   * 组件的方法列表
   */
  methods: {
    _randomNumber(){
      this.setData({
        _rgb:{
        r:Math.floor(Math.random()*256),
        g:Math.floor(Math.random()*256),
        b:Math.floor(Math.random()*256)
        }
      })
    },
    changeR(){
    this.setData({
      '_rgb.r':this.data._rgb.r + 5 > 255 ? 255 : this.data._rgb.r + 5
    })
    },
    changeG(){
      this.setData({
        '_rgb.g' : this.data._rgb.g + 5 > 255 ? 255 : this.data._rgb.g + 5
      })
    },
    changeB(){
      this.setData({
        '_rgb.b' : this.data._rgb.b + 5 > 255 ? 255 : this.data._rgb.b + 5
      })
    },
  },

  observers:{
    '_rgb.**':function(obj){
      this.setData({
        fullcolor:`${obj.r},${obj.g},${obj.b}`
      })
    }
    },
    lifetimes:{
      created(){
        console.log('created')
      },
      attached(){
        console.log('attached')
      }
    },
  pageLifetimes:{
  show:function(){
    this._randomNumber()
  }}
})

插槽

1.什么是插槽

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

2.单个插槽

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

<view>
<view>这里是第一行文本</view>
<slot></slot>
</view>


<newtest>
<view>这里是插入slot里面的内容</view>
</newtest>

3.启用多个插槽

在小程序的自定义组件中,需要使用多 <slot>插槽时,可以在组件的.js文件中,通过在components节点下建立options节点,设置multipleSlots属性为true来进行启用。示例代码如下:

Component({
  options: {
    multipleSlots:'true'
  }
})

4.定义多个插槽

<newtest>
<view slot="before">这里是插入slot-before里面的内容</view>
<view slot="after">这里是插入slot-after里面的内容</view>
</newtest>



<view>
<slot name="before"></slot>
<view>这里是第一行文本</view>
<slot name="after"></slot>
</view>

组件通信-父子组件之间的通信

1.父子组件之间通信的三种方式

①属性绑定

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

②事件绑定

用于子组件向父组件传递数据,可以传递任意数据

③获取组件实例

父组件还可以通过 this.selectComponent() 获取子组件实例对象,这样就可以直接访问子组件的任意数据和方法

2.属性绑定

<!--在父文件中-->
<newtest count="{{count}}"></newtest>
<view>父组件中,count的值是:{{count}}</view>


Page({
  data: {
  count:5
  }
})


<!--在子文件中-->
<view>子组件中,count值是:{{count}}</view>
<button bindtap="addCount">+1</button>


Component({
  behaviors: [myBehavior],
  properties: {
    count:Number
  },
  methods: {
    addCount() {
      this.setData({
        count: this.properties.count + 1
      })
    }
  }
})

3.事件绑定

事件绑定用于实现子向父传值,可以传递任何类型的数据。使用步骤如下:

①在父组件的.js中,定义一个函数,这个函数即将通过自定义事件的形式,传递给子组件

②在父组件的.wxml中,通过自定义事件的形式,将步骤1中定义的函数引用,传递给子组件

③在子组件的.js中,通过调用 this.triggerEvent('自定义事件名称',{/*参数对象*/}),将数据发送到父组件

④在父组件的.js 中,通过 e.detail 获取到子组件传递过来的数据

案例:

// ①在父组件的,js中,定义一个函数,这个函数即将通过自定义事件的形式,传递给子组件
  syncCount(e){
     console.log(e.detail.value)
  },


<!-- ②在父组件的.wxml中,通过自定义事件的形式,将步骤1中定义的函数引用,传递给子组件 -->
<newtest count="{{count}}" bind:sync="syncCount"></newtest>
<!-- 第二种写法
<newtest count="{{count}}" bindsync="syncCount"></newtest> -->
<view>父组件中,count的值是:{{count}}</view>


// ③在子组件的.js中,通过调用 this.triggerEvent('自定义事件名称',{/*参数对象*/}),将数据发送到父组件
methods: {
    addCount() {
      this.setData({
        count: this.properties.count + 1
      })
      this.triggerEvent('sync',{value: this.properties.count})
    }
  }

//④在父组件的.js 中,通过 e.detail 获取到子组件传递过来的数据
syncCount(e){
    this.setData({
      count:e.detail.value
    })
  },

4.获取组件实例

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

<!-- ②在父组件的.wxml中,通过自定义事件的形式,将步骤1中定义的函数引用,传递给子组件 -->
<newtest count="{{count}}" bind:sync="syncCount" class="custom" id="AB"></newtest>
<!-- 第二种写法
<newtest count="{{count}}" bindsync="syncCount"></newtest> -->
<view>父组件中,count的值是:{{count}}</view>
<button bindtap="btp1">点击获取实例对象</button>


btp1(){
  const child= this.selectComponent('.custom')
  child.setData({
    count: child.properties.count +1
  })
  //也可调用子组件的方法
  // child.addCount()
  },

组件的behaviors

1.什么是behaviors

behaviors 是小程序中,用于实现组件间代码共享的特性,类似于 Vue.js 中的"mixins".

2.behaviors的工作方式

每个 behavior 可以包含一组属性、数据、生命周期函数和方法。组件引用它时,它的属性、数据和方法会被合并到组件中。

每个组件可以引用多个 behavior,behavior也可以引用其它behavior。

3.创建behavior

module.exports = Behavior({
data:{
  username:'qihang'
},
properties:{},
methods:{
  addCount(){
    console.log("addCount")
  }
}
})

4.导入并使用behavior

const mybehavior=require('../../behaviors/my-behavior')

Component({
  
  behaviors:[mybehavior]
})

5.behavior中所有可用的节点

 6.同名字段的覆盖和组合规则

组件和它引用的 behavior 中可以包含同名的字段,对这些字段的处理方法如下

如果有同名的属性(properties) 或方法(methods):

1.若组件本身有这个属性或方法,则组件的属性或方法会覆盖 behavior 中的同名属性或方法

2.若组件本身无这个属性或方法,则在组件的 behaviors 字段中定义靠后的 behavior 的属性或方法会覆盖靠前的同名属性或方法;

3.在2的基础上,若存在嵌套引用 behavior 的情况,则规则为: 父behavior 覆盖 子behavior 中的同名属性或方法。

如果有同名的数据字段(data)若同名的数据字段都是对象类型,会进行对象合并

其余情况会进行数据覆盖,覆盖规则为: 组件 > 父behavior  > 子behavior > 靠后的 behavior > 靠前的 behavior。(优先级高的覆盖优先级低的,最大的为优先级最高)

生命周期函数不会相互覆盖,而是在对应触发时机被逐个调用:

对于不同的生命周期函数之间,遵循组件生命周期函数的执行顺序

对于同种生命周期函数,遵循如下规则:

behavior 优先于组件执行

子 behavior 优先于 父 behavior 执行

靠前的 behavior 优先于 后的 behavior 执行

如果同一个 behavior 被一个组件多次引用,它定义的生命周期函数只会被执行一次。

显示全文