# 自定义组件 > 官方文档:https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/ 基础库 1.6.3+ 支持。 ## 创建自定义组件 一个自定义组件由 `json` `wxml` `wxss` `js` 四个文件组成。 ```json // my-component.json — 声明为组件 { "component": true } ``` ```xml {{innerText}} ``` ```css /* my-component.wxss — 样式只作用于本组件 */ .inner { color: red; } ``` ```javascript // my-component.js Component({ properties: { innerText: { type: String, value: 'default value' } }, data: { someData: {} }, methods: { customMethod() {} } }) ``` ### 使用自定义组件 ```json // 页面或组件的 .json { "usingComponents": { "my-component": "/components/my-component/my-component" } } ``` ```xml 这里是插入到 slot 中的内容 ``` **注意事项**: - 标签名只能是小写字母、中划线、下划线的组合 - 组件和页面所在项目根目录名不能以 "wx-" 为前缀 - 使用 `usingComponents` 会使页面的 `this` 原型稍有差异(多了 `selectComponent` 等方法) - 使用 `usingComponents` 时,`setData` 内容不会被深复制(性能优化) ## Component() 构造器 ```javascript Component({ // ===== 组件属性(外部传入) ===== properties: { myProperty: { type: String, // 类型:String, Number, Boolean, Object, Array, null(任意) value: '', // 默认值 observer(newVal, oldVal) { // 属性变化时触发(已不推荐,建议用 observers) } }, myProperty2: String // 简化定义 }, // ===== 组件内部数据 ===== data: { someData: 'initial' }, // ===== 生命周期(推荐写在 lifetimes 中) ===== lifetimes: { created() { // 组件实例刚被创建时 // 此时不能调用 setData,通常用于给 this 添加自定义属性 }, attached() { // 组件实例进入页面节点树时 // 大多数初始化工作在此进行 }, ready() { // 组件在视图层布局完成后 }, moved() { // 组件实例被移动到节点树另一个位置时 }, detached() { // 组件实例被从页面节点树移除时 // 清理工作(如清除定时器) }, error(err) { // 组件方法抛出错误时(基础库 2.4.1+) } }, // ===== 组件所在页面的生命周期 ===== pageLifetimes: { show() { // 页面被展示时 }, hide() { // 页面被隐藏时 }, resize(size) { // 页面尺寸变化时 }, routeDone() { // 页面路由动画完成时(基础库 2.31.2+) } }, // ===== 数据监听器(基础库 2.6.1+) ===== observers: { 'numberA, numberB'(numberA, numberB) { // numberA 或 numberB 变化时触发 this.setData({ sum: numberA + numberB }) }, 'some.subfield'(subfield) { // 监听子数据字段 }, 'arr[12]'(val) { // 监听数组某一项 }, 'some.field.**'(field) { // 使用通配符监听所有子数据字段 }, '**'() { // 监听所有 setData(每次 setData 都触发,慎用) } }, // ===== 方法 ===== methods: { onMyButtonTap() { this.setData({ someData: 'new value' }) }, // 内部方法建议以下划线开头 _myPrivateMethod() { this.setData({ 'A.B': 'myPrivateData' }) } }, // ===== behaviors ===== behaviors: [], // ===== 其他选项 ===== options: { multipleSlots: true, // 启用多 slot(默认只能一个) styleIsolation: 'isolated', // 样式隔离模式 pureDataPattern: /^_/, // 纯数据字段正则 virtualHost: true // 虚拟化组件节点(基础库 2.11.2+) }, // ===== 外部样式类 ===== externalClasses: ['my-class'], // ===== 组件间关系 ===== relations: {}, // ===== 导出(配合 wx://component-export) ===== export() { return { myField: 'myValue' } } }) ``` ## 组件模板和样式 ### 多 slot ```javascript // 组件 js Component({ options: { multipleSlots: true } }) ``` ```xml 组件内部内容 before 内容 after 内容 ``` ### 样式隔离 styleIsolation ```javascript Component({ options: { styleIsolation: 'isolated' // 'isolated'(默认):组件样式完全隔离 // 'apply-shared':页面 wxss 样式会影响组件,但组件不影响页面 // 'shared':页面和组件样式互相影响 } }) ``` 也可在 json 中配置: ```json { "styleIsolation": "isolated" } ``` ### 外部样式类 ```javascript // 组件 Component({ externalClasses: ['my-class'] }) ``` ```xml 这段文本的颜色由外部决定 ``` ## 组件间通信 ### 父 → 子:properties ```xml ``` ### 子 → 父:triggerEvent ```javascript // 子组件 Component({ methods: { onTap() { this.triggerEvent('myevent', { value: 'data' }, { bubbles: false, // 是否冒泡 composed: false, // 是否穿越组件边界 capturePhase: false // 是否有捕获阶段 }) } } }) ``` ```xml ``` ```javascript // 父组件/页面 Page({ onMyEvent(e) { e.detail // { value: 'data' } } }) ``` ### 父获取子实例:selectComponent ```xml ``` ```javascript const child = this.selectComponent('#the-id') // 或 this.selectComponent('.the-class') child.setData({ ... }) child.someMethod() ``` ## behaviors(代码复用) 类似 mixins / traits。 ```javascript // my-behavior.js module.exports = Behavior({ behaviors: [], // 可以引用其他 behavior properties: { myBehaviorProperty: { type: String } }, data: { myBehaviorData: {} }, attached() {}, methods: { myBehaviorMethod() {} } }) ``` ```javascript // 组件中使用 const myBehavior = require('my-behavior') Component({ behaviors: [myBehavior], // 组件自身的 properties/data/methods 会与 behavior 合并 // 同名字段:组件 > behavior > 更早的 behavior // 同名生命周期:都会执行(behavior 先于组件) }) ``` ### 内置 behaviors | behavior | 说明 | |----------|------| | `wx://form-field` | 使组件像表单控件,form 可识别 | | `wx://form-field-group` | form 识别组件内部所有表单控件(2.10.2+) | | `wx://form-field-button` | form 识别组件内部 button(2.10.3+) | | `wx://component-export` | 自定义 selectComponent 返回值(2.2.3+) | ## 纯数据字段 不用于渲染的数据,不会参与 setData 传输,提升性能。 ```javascript Component({ options: { pureDataPattern: /^_/ // 以 _ 开头的字段为纯数据 }, data: { a: true, // 普通数据,参与渲染 _b: true // 纯数据,不参与渲染 } }) ``` ## 组件间关系 relations ```javascript // custom-ul Component({ relations: { './custom-li': { type: 'child', linked(target) {}, // 子组件 attached 时 linkChanged(target) {}, unlinked(target) {} // 子组件 detached 时 } } }) // custom-li Component({ relations: { './custom-ul': { type: 'parent', linked(target) {}, linkChanged(target) {}, unlinked(target) {} } } }) ``` **type 可选值**:`parent` / `child` / `ancestor` / `descendant` ## 抽象节点 componentGenerics ```json // selectable-group.json { "componentGenerics": { "selectable": { "default": "path/to/default" } } } ``` ```xml ``` ## 用 Component 构造器构造页面 ```javascript Component({ properties: { paramA: Number, // 接收页面参数 ?paramA=123 paramB: String }, methods: { onLoad() { this.data.paramA // 123 }, onShow() {}, onPullDownRefresh() {} // 页面生命周期写在 methods 中 } }) ``` 对应 json 需包含 `usingComponents`: ```json { "usingComponents": {} } ``` 好处:可以使用 behaviors 提取所有页面公用代码。 ## 在线查询 如需更详细信息,可抓取: - Component 参考:https://developers.weixin.qq.com/miniprogram/dev/reference/api/Component.html - Behavior 参考:https://developers.weixin.qq.com/miniprogram/dev/reference/api/Behavior.html - 组件生命周期:https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/lifetimes.html