微信小程序组件化开发最佳实践

本文基于「灶台导航」小程序实际开发经验,详解组件化开发的核心要点,涵盖全局组件注册、page-header 封装、props 与事件传递等关键技术。

一、为什么要组件化?

在开发复杂小程序时,如果不进行组件化,会面临以下问题:

问题 表现 后果
代码重复 多个页面复制相同代码 维护困难、bug 多
样式不一致 各页面 UI 风格差异 用户体验割裂
逻辑分散 相同功能多处实现 改一处漏多处
协作困难 多人修改同一文件 冲突频繁

组件化的核心价值:一次封装,多处复用,统一维护


二、组件基础

2.1 创建组件

小程序组件位于 components/ 目录:

2.2 组件基本结构

javascript 复制代码
// components/page-header/page-header.js
Component({
  // 组件属性
  properties: {
    title: {
      type: String,
      value: ''
    },
    showBack: {
      type: Boolean,
      value: true
    }
  },

  // 组件数据
  data: {
    statusBarHeight: 0
  },

  // 组件生命周期
  lifetimes: {
    attached() {
      const systemInfo = wx.getSystemInfoSync()
      this.setData({
        statusBarHeight: systemInfo.statusBarHeight
      })
    }
  },

  // 组件方法
  methods: {
    onBack() {
      this.triggerEvent('back')
    }
  }
})

2.3 组件配置

json 复制代码
// components/page-header/page-header.json
{
  "component": true,
  "usingComponents": {}
}

三、全局组件注册

3.1 在 app.json 中注册

json 复制代码
// app.json
{
  "pages": [
    "pages/index/index",
    "pages/cook/cook"
  ],
  "usingComponents": {
    "page-header": "/components/page-header/page-header",
    "loading": "/components/loading/loading",
    "empty-state": "/components/empty-state/empty-state",
    "modal": "/components/modal/modal"
  }
}

优势

  • 所有页面可直接使用,无需重复声明
  • 统一管理,修改方便
  • 减少页面 JSON 配置量

3.2 页面级组件注册

如果组件只在特定页面使用,可在页面 JSON 中注册:

json 复制代码
// pages/cook/cook.json
{
  "usingComponents": {
    "timer": "/components/timer/timer"
  }
}

四、Props 属性传递

4.1 属性定义

javascript 复制代码
Component({
  properties: {
    // 简写
    title: String,
    
    // 完整写法
    showBack: {
      type: Boolean,
      value: true,          // 默认值
      observer: function(newVal, oldVal) {
        // 属性变化时的回调
        console.log('showBack changed:', newVal)
      }
    },
    
    // 复杂类型
    userInfo: {
      type: Object,
      value: {}
    },
    
    // 数组类型
    menuList: {
      type: Array,
      value: []
    }
  }
})

4.2 页面中传递属性

xml 复制代码
<!-- 页面中使用组件 -->
<page-header 
  title="烹饪中"
  showBack="{{true}}"
  user-info="{{userInfo}}"
  bind:back="onBack"
/>

注意事项

  • 字符串可以直接传递:title="标题"
  • 布尔值、数字、对象、数组需要使用双花括号:showBack="{``{true}}"
  • 属性名建议使用 kebab-case:user-info 而非 userInfo

五、事件传递

5.1 子组件触发事件

javascript 复制代码
// components/page-header/page-header.js
Component({
  methods: {
    onBack() {
      // 触发事件,可携带数据
      this.triggerEvent('back', {
        from: 'header',
        timestamp: Date.now()
      })
    },
    
    onRightTap() {
      // 触发带冒号的事件名
      this.triggerEvent('righttap', {
        action: 'save'
      })
    }
  }
})

5.2 父页面监听事件

xml 复制代码
<!-- pages/cook/cook.wxml -->
<page-header 
  title="烹饪中"
  bind:back="onBack"
  bind:righttap="onRightAction"
/>
javascript 复制代码
// pages/cook/cook.js
Page({
  onBack(e) {
    // 获取事件携带的数据
    console.log(e.detail.from)     // 'header'
    console.log(e.detail.timestamp)
    
    // 业务逻辑
    wx.navigateBack()
  },
  
  onRightAction(e) {
    if (e.detail.action === 'save') {
      this.saveProgress()
    }
  }
})

5.3 事件命名规范

事件名 使用场景
bind:back 返回按钮点击
bind:confirm 确认操作
bind:cancel 取消操作
bind:change 值变化
bind:tap 点击

六、插槽(Slot)使用

6.1 单插槽

javascript 复制代码
// 组件定义
Component({
  options: {
    multipleSlots: false  // 默认单插槽
  }
})
xml 复制代码
<!-- 组件模板 -->
<view class="card">
  <view class="header">{{title}}</view>
  <slot></slot>  <!-- 插槽位置 -->
</view>
xml 复制代码
<!-- 页面使用 -->
<card title="标题">
  <view>这里是插入的内容</view>
</card>

6.2 多插槽

javascript 复制代码
// components/modal/modal.js
Component({
  options: {
    multipleSlots: true
  },
  
  properties: {
    title: String
  }
})
xml 复制代码
<!-- components/modal/modal.wxml -->
<view class="modal">
  <view class="modal-header">
    <slot name="header"></slot>
  </view>
  <view class="modal-body">
    <slot name="body"></slot>
  </view>
  <view class="modal-footer">
    <slot name="footer"></slot>
  </view>
</view>
xml 复制代码
<!-- 页面使用 -->
<modal>
  <view slot="header">自定义标题</view>
  <view slot="body">内容区域</view>
  <view slot="footer">
    <button>确定</button>
  </view>
</modal>

七、组件通信进阶

7.1 父组件调用子组件方法

javascript 复制代码
// 页面中
Page({
  onReady() {
    // 获取组件实例
    this.modal = this.selectComponent('#modal')
  },
  
  showModal() {
    // 调用组件方法
    this.modal.show()
  },
  
  hideModal() {
    this.modal.hide()
  }
})
javascript 复制代码
// 组件中
Component({
  methods: {
    show() {
      this.setData({ visible: true })
    },
    hide() {
      this.setData({ visible: false })
    }
  }
})

7.2 兄弟组件通信

通过父组件中转:

javascript 复制代码
// 页面
Page({
  data: {
    sharedData: null
  },
  
  onChildAChange(e) {
    this.setData({ sharedData: e.detail.value })
  }
})
xml 复制代码
<!-- 页面模板 -->
<child-a bind:change="onChildAChange" />
<child-b data="{{sharedData}}" />

7.3 全局事件总线

javascript 复制代码
// utils/eventBus.js
class EventBus {
  constructor() {
    this.events = {}
  }
  
  on(event, callback) {
    if (!this.events[event]) {
      this.events[event] = []
    }
    this.events[event].push(callback)
  }
  
  emit(event, data) {
    if (this.events[event]) {
      this.events[event].forEach(cb => cb(data))
    }
  }
  
  off(event, callback) {
    if (this.events[event]) {
      this.events[event] = this.events[event].filter(cb => cb !== callback)
    }
  }
}

module.exports = new EventBus()

八、组件最佳实践

8.1 命名规范

类型 命名规范 示例
组件目录 kebab-case page-header/
组件文件 kebab-case page-header.js
属性名 kebab-case show-back
事件名 小写 bind:back
方法名 camelCase onBackTap()

8.2 组件职责单一

javascript 复制代码
// ❌ 不推荐:一个组件做太多事
Component({
  properties: {
    type: String,  // 'header' | 'footer' | 'sidebar'
    // ...
  }
})

// ✅ 推荐:职责分离
// page-header 组件只负责头部
// page-footer 组件只负责底部

9.3 避免 setData 过度使用

javascript 复制代码
// ❌ 不推荐
this.setData({ a: 1 })
this.setData({ b: 2 })
this.setData({ c: 3 })

// ✅ 推荐
this.setData({
  a: 1,
  b: 2,
  c: 3
})

十、总结

组件化开发核心要点:

要点 说明
全局注册 app.json 中声明,所有页面可用
Props 传递 属性定义、类型校验、默认值
事件通信 triggerEvent 触发,bind 监听
插槽使用 单插槽、具名插槽扩展组件
职责单一 一个组件只做一件事

通过组件化开发,可以显著提升代码复用性和可维护性。


作者:「倒灶了队」

项目:灶台导航 - 微信小程序

更新时间:2026-03-29

相关推荐
曲江涛2 小时前
微信小程序 摄像头 授权同页面丝滑调用
微信小程序
code_Bo2 小时前
kiro生成小程序商业案例
前端·微信小程序·小程序·云开发
编程迪4 小时前
基于SpringBoot开发的预约停车系统共享停车位小程序app
小程序·停车场小程序·预约停车·错峰出行·共享车位app
云起SAAS4 小时前
早晚安打卡签到小程序完整源码 | 三级分销+红包广告+PC后台 | 商业级系统
小程序
职豚求职小程序4 小时前
浙商银行笔试题库小程序练习2026新版题库
小程序
Kingexpand_com4 小时前
旅游小程序选型指南:模板与定制开发全解析
小程序·旅游·软件开发·小程序开发·旅游小程序·旅行·定制开发
克里斯蒂亚诺更新4 小时前
微信小程序引入vant weapp,button宽度100%
微信小程序·小程序
一品威客网4 小时前
租车小程序 APP 版本开发 全端适配高效用车体验一站式搭建
小程序
nhc08814 小时前
贵阳纳海川·花卉游戏行业解决方案
人工智能·游戏·微信小程序·软件开发·小程序开发