组件构成
自定义一个小程序可在Compoment文件夹内新建一个文件夹,更改为组件名
再右键新建components创建组件
会看到新建了四个文件
分别为
- testComponent.json
- testComponent.wxml
- testComponent.wxss
- testComponent.js
打开json文件可以看到
必须将 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 获取组件实例,再调用实例的方法
- 给组件添加标识(ID/Class)
<my-component id="myComponentId"></my-component>
- 获取组件实例
const component = this.selectComponent("#myComponentId");
- 调用子组件方法
component.resetCount();