自定义组件

组件的创建与引用

创建组件

根目录>创建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