自定义组件

组件的创建与引用

创建组件

根目录>创建components>test文件夹>右键新建component

会自动生成组件对应的四个文件

为保证目录结构清晰,建议把不同组件存放到单独目录中

引用组件

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

局部引用

在页面.json 文件中引用叫做局部引用

1
2
3
4
5
6
7
8
//页面.json 文件
{
"usingComponents": {
"my-test1": "/components/test/test1"
}
}
//在页面.wxml中使用组件
<my-test1></my-test1>

全局引用

在app.json 文件中引用叫做局部引用

1
2
3
4
5
{
"usingComponents": {
"my-test1": "/components/test/test1"
}
}

组件和页面的区别

表面看,页面和组件都是由js json wxml wxss四个文件组成,但是组件的js和json文件明显不同

  • 组件json文件中需要声明"component": true属性
  • 组件js文件中调用的是Component()函数
  • 组件事件处理函数需要定义到methods节点中

样式

组件样式隔离

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

注意点:

  • app.wxss中的全局样式对组件无效
  • 只有class选择器会有样式隔离效果,id 属性 标签选择器不受样式隔离影响
  • 建议在组件 和引用组件页面中建议使用class选择器,不要使用id 属性 标签选择器

修改组件样式隔离选项

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

1
2
3
4
5
6
7
8
9
10
// 在组件js文件中新增如下属性
Component({
options: {
styleIsolation: 'shared'
},

// 或在组件json文件中新增如下配置
{
"styleIsolation": "isolated"
}

styleIsolation可选值

可选值 默认值 描述
isolated 是 启用样式隔离
apply-shared 否 页面wxss样式将影响到自定义组件,但自定义组件wxss中的样式不会影响到页面
shared 否 表示页面wxss样式和自定义组件wxss会相互影响

数据方法属性

data数据

在小程序组件中,用于组件模块渲染的私有数据,需要定义到data节点中

1
2
3
4
5
6
Component({
// 组件初始数据
data: {
count: 0
}
})

methods方法

在小程序组件中,事件处理函数和自定义方法需要定义到methods节点中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Component({
methods: {
// 点击事件处理函数
addCount() {
if (this.data.count >= this.properties.max) return
this.setData({
count: this.data.count + 1,
max: this.properties.max + 1
})

this._showCount()
},
_showCount() {
wx.showToast({
title: 'count是' + this.data.count,
icon: 'none'
})
}
}
})

properties属性

在小程序中,properties是组件的对外属性,用来接收外界传递到组件中的数据

1
2
3
4
5
6
7
8
9
10
11
Component({
properties: {
// 第一种方式:简化的方式
// max: Number
// 第二种方式:完整的定义方式
max: {
type: Number,
value: 10
}
}
})

data和properties的区别

  • 用法相同,都是可读可写
  • data倾向于存储组件的私有数据
  • properties倾向于存储外界传递到组件中的数据

使用data数据和properties属性本质上没有区别,因此properties属性的值可用于页面渲染,或用setData为properties中的属性重新赋值

数据监听器

数据监听器用于监听和响应任何属性和数据字段的变化,从而执行特定的操作

1
2
3
4
5
6
7
Component({
observers: {
'字段A, 字段B': function(字段A的新值, 字段B的新值) {
// do something
}
}
})

基本用法

组件UI结构

1
2
3
4
<view>{{n1}} + {{n2}} = {{sum}}</view>

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

组件js文件代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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: newN1 + newN2
})
}
}
})

监听对象属性的变化

数据监听器支持监听对象中单个或多个属性的变化

1
2
3
4
5
6
7
8
9
10
11
Component({
observes: {
'对象.属性A, 对象.属性B': function(属性A的新值, 属性B的新值) {
//触发监听器的三种情况
// 为属性A赋值:使用setData设置this.data.对象.属性A时触发
// 为属性B赋值:使用setData设置this.data.对象.属性B时触发
// 直接为对象赋值: 使用setData设置this.data.对象时触发
// do something
}
}
})

监听对象中所有属性的变化

如某个对象中需要被监听的属性太多,为方便,可以使用通配符**来监听 对象中所有属性的变化

1
2
3
4
5
6
7
observers: {
'rgb.**': function(obj) {
this.setData({
fullColor: '${obj.r}, ${obj.g}, ${onj.b}'
})
}
}

纯数据字段

纯数据字段是指不用于页面渲染的data字段,有助于提高页面更新的性能

使用规则

在Component构造器的options节点中,指定pureDataPattern为一个正则表达式,字段名符合这个正则表达式的字段将称为纯数据字段

1
2
3
4
5
6
7
8
9
Component({
options: {
pureDataPattern: /^_/
},
data: {
a: true, // 普通数据字段
_b: true, // 纯数据字段
}
})

组件的生命周期

组件全部生命周期函数

生命周期函数 参数 说明
created 无 在组件实例刚被创建时执行
attached 无 在租件实例进入页面节点树时执行
ready 无 在组件在视图布局完成后执行
moved 无 在组件实例被移动到节点数另一个位置时执行
detached 无 在组件实例被从也缪按节点树移除时执行
error object error 当组件方法抛出错误时执行

组件主要生命周期函数

created

  • 此时不能调用setData
  • 通常在这个生命周期函数中,只用于给组件的this添加一些自定义属性字段

attached

  • 此时this.data已经被初始化完毕
  • 这个生命周期函数很有用,很多初始化工作可以在这个时机进行

detached

  • 退出一个页面时会触发页面内每个自定义组件的detached生命周期函数
  • 适合做一些清理工作

创建生命周期函数(Lifetimes节点)

目前生命周期函数推荐定义在lifetimes字段中进行声明,优先级最高;也可直接定义在Component构造器的第一级参数中

1
2
3
4
5
6
7
8
9
10
Component({
//推荐用法
lifetimes: {
attached() {},
detached() {},
},
//旧方法
attached() {},
detached() {},
})

组件所在页面的生命周期

有时自定义组件的行为依赖于页面状态的变化,此时需要用到组件所在页面的生命周期,例如每当触发页面show 生命周期函数时,可以重新生成一个随机的RGB颜色值

生命周期函数 参数 描述
show 无 组件所在页面被展示时执行
hide 无 组件所在页面被隐藏时执行
resize object size 组件所在页面尺寸发生变化时执行

创建(pageLifetimes节点)

组件所在页面生命周期函数,需要定义在pageLifetimes节点中

1
2
3
4
5
6
Component({
pageLifetimes: {
show: function() {},
resize: function(size) {}
}
})

插槽

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

单个插槽

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

多个插槽

定义多个插槽时需要在js文件中启用

1
2
3
4
5
Component({
options: {
multipleSlots: true // 启用多个插槽
}
})

使用时多个插槽时需要为<slot>添加类名,需要用slot属性来将节点插入到不同<slot>中

父子组件通信

三种方式

  1. 属性绑定

  2. 事件绑定

  3. 获取组件实例

属性绑定

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

1
2
3
4
5
6
7
// 父组件的data节点
data: {
count: 0
}
//父组件wxml 结构
<my-test3 count="{{count}}"></my-test>
<view> 父组件中,count值为{{count}}</view>

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

1
2
3
4
5
6
//子组件properties节点
properties: {
count: Number
}
//子组件wxml结构
<text>子组件中,count值为{{count}}</text>

事件绑定

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

  1. 在父组件js中,定义一个函数,这个函数即将通过自定义事件的形式,传递给子组件
  2. 在父组件wxml中,通过自定义事件形式,将步骤一定义的函数引用,传递给子组件
  3. 在子组件js中,通过调用this.triggerEvent('自定义事件名称',{参数对象}),将数据发送到父组件
  4. 在父组件js中,通过e.detail获取到子组件传递过来的数据

获取组件实例

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

behaviors

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

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

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

创建behavior

调用Behavior(object object)方法即可创建一个共享的behavior实例对象,供所有组件使用

1
2
3
4
5
6
7
8
9
10
// 使用Behavior()方法,创建实例对象
// 并使用module.exports 将 behavior实例对象共享出去
module.exports = Behavior({
//属性节点
properties; {},
//私有数据节点
data: { uesrname: 'zs'},
//事件处理函数和自定义方法节点
methods: {},
})

导入并使用behavior

在组件中,使用require()方法导入需要的behavior,挂载后即可访问behavior中的数据或方法,

1
2
3
4
5
6
7
// 使用require() 导入需要自定义 behavior模块
const myBehavior = require("../../behaviors/my-behavior")

Component({
// 将导入的behavior实例对象,挂载到 behavior数组节点中,即可生效
behavior: [myBehavior],
})

behavior所有可用节点

可用节点 类型 必填 描述
properties object map 否 同组件的属性
data object 否 同组件的数据
methods object 否 同自定义组件的方法
behaviors string array 否 引入其他的behavior
created function 否 生命周期函数
attached function 否 生命周期函数
ready function 否 生命周期函数
moved function 否 生命周期函数
detached function 否 生命周期函数

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

https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/behaviors.html