组件构成

自定义一个小程序可在Compoment文件夹内新建一个文件夹,更改为组件名
再右键新建components创建组件
会看到新建了四个文件
分别为

  • testComponent.json
  • testComponent.wxml
  • testComponent.wxss
  • testComponent.js

打开json文件可以看到

1
2
3
{
"component": true
}

必须将 component设为 true声明这是一个自定义组件:

组件编写

组件编写总体上和写页面差不多,可使用{{}}绑定数据

组件结构编写(wmxl)

1
2
3
4
5
6
<!-- 自定义提示卡片组件结构 -->
<view class="tip-card {{type === 'warning' ? 'warning' : 'info'}}">
<view class="tip-title">{{title}}</view>
<view class="tip-content">{{content}}</view>
<button bindtap="onCloseTap" class="tip-close">关闭</button>
</view>

组件样式编写(wxss)

默认开启样式隔离(组件样式不会影响页面,页面样式也不会影响组件)
与页面写法一致,略

组件逻辑编写(js)

核心:Component 构造器

组件的运行方式(核心:生命周期 + 执行逻辑)
自定义组件的运行核心是生命周期函数和数据响应式

总体代码
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
Component({
// 【基础配置】组件全局选项(样式隔离、多slot等)
options: {
styleIsolation: "isolated", // 样式隔离(默认)
multipleSlots: true // 启用多slot支持
},

// 【外部样式】允许父组件传入样式类覆盖组件样式
externalClasses: ["custom-class"],

// 【属性定义】父组件向子组件传参(核心)
properties: {
title: {
type: String,
value: "默认标题",
observer(newVal, oldVal) {
// 属性值变化时的回调
}
},
type: {
type: String,
value: "info",
optionalTypes: [String, Number], // 多类型支持
validator(value) {
// 自定义校验规则
return ["info", "warning", "error"].includes(value);
}
}
},

// 【私有数据】组件内部状态(响应式)
data: {
isShow: true,
count: 0
},

// 【数据监听】监听data/properties变化(比observer更强大)
observers: {
"count, type": function(newCount, newType) {
// 监听多个字段变化
console.log("count或type变化:", newCount, newType);
},
// 监听对象属性变化(通配符)
"userInfo.name": function(newName) {
console.log("用户名变化:", newName);
}
},

// 【纯数据字段】不参与渲染的字段(优化性能)
pureDataPattern: /^_/, // 以_开头的字段为纯数据字段

// 【组件生命周期】组件自身的生命周期(核心)
lifetimes: {
created() {}, // 组件创建
attached() {}, // 组件挂载
ready() {}, // 组件渲染完成
moved() {}, // 组件移动节点树
detached() {} // 组件卸载
},

// 【页面生命周期】监听组件所在页面的生命周期
pageLifetimes: {
show() {}, // 页面显示
hide() {}, // 页面隐藏
resize() {} // 页面尺寸变化
},

// 【组件关系】定义与其他组件的关联(父子/兄弟)
relations: {
"/components/tip-item/tip-item": {
type: "child", // 关联的是子组件
linked(target) {}, // 子组件被添加时触发
unlinked(target) {} // 子组件被移除时触发
}
},

// 【方法定义】事件处理/自定义业务逻辑
methods: {
// 内部方法
_updateCount() {
this.setData({ count: this.data.count + 1 });
},
// 事件处理方法(绑定到wxml)
onCloseTap() {
// 子向父通信:触发自定义事件
this.triggerEvent("close", { id: 123 }, { bubbles: true });
// 修改私有数据
this.setData({ isShow: false });
}
},

behaviors: [require("../behaviors/common-behavior.js")]
});


properties:父组件可以传入子组件的参数

例:

1
2
3
4
5
6
7
8
properties: {
title: {
type: String,
value: "默认标题",
optionalTypes: [String, Number],
observer(newVal, oldVal) {
}
}

规定了

  • type:类型
  • value:参数值
  • observer:Function 属性值变化时调用的回调
  • optionalTypes: 多类型支持(可选),
  • validator:自定义校验规则函数(可选),父组件传递值时调用,返回true校验成功值替换,返回false则失败使用默认值 例: validator(value) { // 仅允许0/1/2 return [0, 1, 2].includes(value); }

data:组件私有数据

与页面使用方法一致,组件内部数据,仅组件自身可修改

methods:方法定义

-methods 包含组件的所有方法,分为两类:

  • 事件处理方法:绑定到 wxml 的事件(如 bindtap=”onCloseTap”);
  • 内部业务方法:组件内部调用(建议以 _ 开头,区分外部调用)。
示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

methods: {
// 事件处理方法(wxml中绑定)
onButtonTap(e) {
console.log("点击事件参数:", e);
// 调用内部方法
this._handleLogic();
},

// 内部业务方法(私有)
_handleLogic() {
// 子向父通信:触发名为"myevent"的自定义事件,传递数据
this.triggerEvent(
"myevent", // 事件名
{ msg: "子组件消息" }, // 传递的参数(父组件通过e.detail获取)
{ // 事件配置
bubbles: true, // 是否冒泡
composed: true // 是否穿越组件边界
}
);
}
}

lifetimes:组件自身生命周期(核心)

以下方法最好写在lifetimes下
created(创建)→ attached(挂载)→ ready(渲染完成)→ [moved(移动,极少用)] → detached(卸载)
例:

1
2
3
4
5
lifetimes: {
created() {
console.log("组件创建:仅初始化数据");
},
}

pageLifetimes:监听所在页面的生命周期

分为show hide resize
示例

1
2
3
4
5
6
7
8
pageLifetimes: {
show() {
console.log("页面显示:刷新组件数据");
},
hide() {
console.log("页面隐藏:暂停视频播放");
}
}

observers:数据监听器

监听 data/properties 的变化,支持「多字段监听」「通配符监听嵌套对象」,替代单个属性的 observer,更灵活。

1
2
3
4
5
6
7
8
9
observers: {
// 监听单个字段
"count": function(newCount) {
console.log("count变为:", newCount);
},
// 监听多个字段(任意一个变化就触发)
"title, type": function(newTitle, newType) {
console.log("标题或类型变化:", newTitle, newType);
},

组件之间通信

页面向组件传参

在wxml页面动态传参

1
2
3
4
5
6
<my-component 
id="myComponentId" <!-- 给组件加ID,用于获取组件实例 -->
title="{{pageTitle}}" <!-- 动态传参:绑定页面data的pageTitle -->
count="{{pageCount}}" <!-- 动态传参:绑定页面data的pageCount -->
bind:innerChange="handleInnerChange" <!-- 监听组件发送的事件 -->
></my-component>

组件向页面传递

通过在方法中使用 this.triggerEvent("innerChange/事件名",{传递参数})

页面在使用组件时通过绑定 bind:innerChange="handleInnerChange"来监听子组件事件

页面js监听写法
handleInnerChange(e) { console.log("接收组件事件:", e.detail.newCount); },

父组件调用子组件方法

获取实例,直接使用
先通过 selectComponent 获取组件实例,再调用实例的方法

  1. 给组件添加标识(ID/Class)<my-component id="myComponentId"></my-component>
  2. 获取组件实例 const component = this.selectComponent("#myComponentId");
  3. 调用子组件方法component.resetCount();