Files
Neo-ZQYY/_DEL/wechat-miniprogram/steering/custom-component.md
2026-03-15 10:15:02 +08:00

9.1 KiB
Raw Permalink Blame History

自定义组件

官方文档: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 识别组件内部 button2.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 提取所有页面公用代码。

在线查询

如需更详细信息,可抓取: