9.1 KiB
9.1 KiB
自定义组件
官方文档:https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/
基础库 1.6.3+ 支持。
创建自定义组件
一个自定义组件由 json wxml wxss js 四个文件组成。
// my-component.json — 声明为组件
{ "component": true }
<!-- my-component.wxml -->
<view class="inner">
{{innerText}}
<slot></slot>
</view>
/* my-component.wxss — 样式只作用于本组件 */
.inner { color: red; }
// my-component.js
Component({
properties: {
innerText: {
type: String,
value: 'default value'
}
},
data: {
someData: {}
},
methods: {
customMethod() {}
}
})
使用自定义组件
// 页面或组件的 .json
{
"usingComponents": {
"my-component": "/components/my-component/my-component"
}
}
<!-- 页面 wxml -->
<my-component inner-text="Some text">
<view>这里是插入到 slot 中的内容</view>
</my-component>
注意事项:
- 标签名只能是小写字母、中划线、下划线的组合
- 组件和页面所在项目根目录名不能以 "wx-" 为前缀
- 使用
usingComponents会使页面的this原型稍有差异(多了selectComponent等方法) - 使用
usingComponents时,setData内容不会被深复制(性能优化)
Component() 构造器
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
// 组件 js
Component({
options: { multipleSlots: true }
})
<!-- 组件 wxml -->
<view>
<slot name="before"></slot>
<view>组件内部内容</view>
<slot name="after"></slot>
</view>
<!-- 使用 -->
<my-component>
<view slot="before">before 内容</view>
<view slot="after">after 内容</view>
</my-component>
样式隔离 styleIsolation
Component({
options: {
styleIsolation: 'isolated'
// 'isolated'(默认):组件样式完全隔离
// 'apply-shared':页面 wxss 样式会影响组件,但组件不影响页面
// 'shared':页面和组件样式互相影响
}
})
也可在 json 中配置:
{ "styleIsolation": "isolated" }
外部样式类
// 组件
Component({
externalClasses: ['my-class']
})
<!-- 组件 wxml -->
<view class="my-class">这段文本的颜色由外部决定</view>
<!-- 使用时 -->
<my-component my-class="red-text"/>
组件间通信
父 → 子:properties
<my-component prop-a="{{dataA}}" prop-b="staticValue"/>
子 → 父:triggerEvent
// 子组件
Component({
methods: {
onTap() {
this.triggerEvent('myevent', { value: 'data' }, {
bubbles: false, // 是否冒泡
composed: false, // 是否穿越组件边界
capturePhase: false // 是否有捕获阶段
})
}
}
})
<!-- 父组件/页面 -->
<my-component bind:myevent="onMyEvent"/>
<!-- 或 bindmyevent="onMyEvent" -->
// 父组件/页面
Page({
onMyEvent(e) {
e.detail // { value: 'data' }
}
})
父获取子实例:selectComponent
<my-component id="the-id" class="the-class"/>
const child = this.selectComponent('#the-id')
// 或 this.selectComponent('.the-class')
child.setData({ ... })
child.someMethod()
behaviors(代码复用)
类似 mixins / traits。
// my-behavior.js
module.exports = Behavior({
behaviors: [], // 可以引用其他 behavior
properties: {
myBehaviorProperty: { type: String }
},
data: {
myBehaviorData: {}
},
attached() {},
methods: {
myBehaviorMethod() {}
}
})
// 组件中使用
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 传输,提升性能。
Component({
options: {
pureDataPattern: /^_/ // 以 _ 开头的字段为纯数据
},
data: {
a: true, // 普通数据,参与渲染
_b: true // 纯数据,不参与渲染
}
})
组件间关系 relations
// 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
// selectable-group.json
{
"componentGenerics": {
"selectable": {
"default": "path/to/default"
}
}
}
<!-- selectable-group.wxml -->
<view wx:for="{{labels}}">
<selectable disabled="{{false}}"></selectable>
</view>
<!-- 使用时指定具体组件 -->
<selectable-group generic:selectable="custom-radio"/>
用 Component 构造器构造页面
Component({
properties: {
paramA: Number, // 接收页面参数 ?paramA=123
paramB: String
},
methods: {
onLoad() {
this.data.paramA // 123
},
onShow() {},
onPullDownRefresh() {}
// 页面生命周期写在 methods 中
}
})
对应 json 需包含 usingComponents:
{ "usingComponents": {} }
好处:可以使用 behaviors 提取所有页面公用代码。
在线查询
如需更详细信息,可抓取: