
商品卡片在列表页、详情页、搜索页重复粘贴,改一个字段要同时动三处。小程序自定义组件把这类结构收进独立单元:properties 接收数据,triggerEvent 回传交互结果,页面只负责编排。
一、组件化的收益与边界
1. 复制粘贴带来的三类问题
小程序页面由 wxml、js、wxss、json 四个文件组成。同一块结构在多页面出现时,直接复制会造成样式冲突(同名 class 相互覆盖)、逻辑分叉(列表页加了埋点、详情页漏了)、包体膨胀。
2. 抽成组件后的调用约定
调用方只关心三件事:传什么数据进去、监听什么事件出来、样式怎么覆盖。组件内部状态由自身 setData 管理,不依赖页面作用域,也能新建空白页面单独调试。
二、Component 构造器与数据传递
1. 最小可用组件
组件同样四个文件,区别是 json 必须声明 "component": true,漏写会被当成普通节点,properties 全部为空。视图层绑定事件名指向 methods 中的方法,逻辑层用 Component 注册:
Component({
properties: { price: { type: Number, value: 0 } },
methods: {
onTap() {
this.setData({ active: !this.data.active })
this.triggerEvent('select', { id: this.data.id })
}
}
})
2. properties 的类型陷阱
type: Number 时父组件传字符串 '12',框架会尝试转换,失败时不抛错、只保留原值,列表渲染不要依赖隐式转换。properties 赋值还是异步的:父组件改值后,子组件 this.data 要等下一轮渲染才更新,同步读取仍是旧值。依赖多个属性的派生值用 observers 处理:
observers: { 'price, count'(a, b) { this.setData({ total: (a * b).toFixed(2) }) } }
监听字段逗号分隔,回调参数按声明顺序传入。observers 在组件初始化时也会触发一次,不要在回调里写只允许执行一次的逻辑。
三、事件通信与样式隔离
1. triggerEvent 向上传值
子组件抛事件的第二个参数是事件对象,父组件从 event.detail 取。事件名不要用驼峰,开发者工具会告警。第三个参数控制是否冒泡、是否跨组件边界,默认都不开启。确需主动调用子组件方法时用 this.selectComponent('#card'),选择器用 id 最稳,class 在同类组件并存时只命中第一个。
2. 样式隔离与外部样式类
styleIsolation 默认 isolated,组件内外样式互不影响;apply-shared 允许页面样式影响组件;shared 双向影响,业务组件保持默认即可。让调用方定制样式用 externalClasses 开口子:
Component({ externalClasses: ['ext-class'] })
组件 wxss 里不要写标签选择器,隔离机制对它不生效,容易误伤外部节点。
关键配置提示
- 组件 json 必须写
"component": true,漏写会导致 properties 收不到值。 - properties 与 data 不要同名字段,同名时以 properties 为准并触发告警。
- 页面与组件通信优先走 triggerEvent,selectComponent 仅用于确需主动调方法的场景。

快来评论,快来抢沙发吧~