简介
本规范面向 DouPHP 小程序的组件开发,聚焦于统一的接口定义、事件机制、插槽使用、生命周期管理以及配置选项标准。文档以实际代码为依据,结合导航栏组件(navbar)作为范例,给出从创建到使用的完整流程说明,帮助团队在统一规范下高效协作。
项目结构
小程序工程位于 miniprogram 目录下,包含 default 与 company 两套主题/业务实现。每个主题均提供:
- 应用入口 app.ts:负责全局初始化、错误处理、自动更新、推广参数解析等
- 组件目录 components:复用 UI 能力,如 navbar
- 页面 pages、服务 services、状态 stores、工具 utils、类型 types 等
graph TB
subgraph "小程序应用"
A["app.ts<br/>全局初始化/错误/更新"]
B["components/navbar<br/>导航栏组件"]
C["pages/*<br/>业务页面"]
D["services/*<br/>网络/上传等服务"]
E["stores/*<br/>全局状态"]
end
A --> B
A --> C
A --> D
A --> E
C --> B
核心组件
- 导航栏组件(navbar):提供标题、背景色、标题色、滚动透明度、返回/首页跳转、调试入口等功能,支持具名插槽扩展布局。
- 应用入口(app.ts):注册 HTTP 拦截器、引导全局 store、解析推广参数、计算导航高度、自动更新、全局错误钩子。
架构总览
小程序启动时,app.ts 完成全局初始化;页面加载后引入并使用 navbar 组件;组件通过 properties 接收父级数据,通过 methods 触发交互;WXML 中通过 slot 进行内容注入。
sequenceDiagram
participant App as "应用(app.ts)"
participant Page as "页面(pages/*)"
participant Nav as "导航栏组件(navbar.ts/wxml)"
participant WX as "微信API"
App->>App : onLaunch() 初始化全局数据/错误/更新
Page->>Nav : 渲染并传入 properties(title, backgroundColor, titleColor, scrollOpacity, url, showMenu)
Nav->>WX : 读取窗口/设备信息(由App.globalData提供)
Nav-->>Page : 暴露方法(goBack/goHome/openDebug)
Page->>Nav : 点击菜单/标题区域
Nav->>WX : navigateBack/switchTab/navigateTo
详细组件分析
属性(props)定义规范
- 类型声明:优先使用具体类型(String、Number、Boolean),必要时使用 null 表示任意类型并在 observer 中做类型归一化。
- 默认值:为所有可配置项设置合理的默认值,保证组件在未传参时仍可正常渲染。
- 验证规则:通过 observer 对输入进行校验与转换,避免脏数据进入渲染层。
- 示例参考:
- 标题、背景色、标题色:允许任意类型,内部转换为字符串或保持原样
- 滚动透明度:Number 类型,范围 0~1
- 返回 URL、是否显示菜单:String/Boolean 类型,带默认值
事件绑定机制
- 自定义事件:组件内部通过 bindtap 绑定方法,调用 wx 路由 API 完成跳转;如需向父级传递事件,可在 methods 中通过 this.triggerEvent('eventName', payload) 触发。
- 参数传递:事件回调可通过 e.currentTarget.dataset. 获取 data- 属性值。
- 冒泡处理:默认事件会冒泡,若需阻止可使用 stopPropagation 或在 WXML 中使用 catch 替代 bind。
插槽(slot)使用方式
- 默认插槽:未提供 center 插槽时,回退为标题展示。
- 具名插槽:支持 left、center、right 三个命名插槽,便于灵活定制导航栏左右区域与中心内容。
- 作用域插槽:当前实现未使用作用域插槽;如需将组件内部状态暴露给插槽内容,可在 properties 中暴露只读字段并通过 slot-scope 传递。
生命周期管理
- attached:组件实例被插入节点时触发,用于初始化调试入口可见性等逻辑。
- ready:组件所在页面完成首次渲染后可执行 DOM 相关操作(如有需要)。
- detached:组件实例被移除时触发,用于清理定时器、监听器等资源。
- 注意:当前实现仅使用了 lifetimes.attached,建议按需补充其他阶段。
组件配置选项标准格式
- JSON 配置:组件根节点声明 "component": true,启用组件模式。
- 多插槽:通过 options.multipleSlots: true 开启多插槽支持。
- 样式隔离:遵循小程序组件样式隔离原则,避免全局污染。
- 平台兼容:根据平台差异动态计算导航高度,确保在不同设备上表现一致。
依赖关系分析
- 组件依赖应用全局数据:navbar 通过 getApp().globalData 获取状态栏、导航栏高度等信息。
- 组件依赖工具函数:goBack 使用 douPageTo 进行页面跳转;openDebug 使用 wx.navigateTo。
- 应用依赖服务与存储:http 拦截器统一处理 UNAUTHORIZED 登出;bootstrapStores 初始化全局状态。
graph LR
App["app.ts"] --> Store["stores/index.js<br/>bootstrapStores"]
App --> Http["services/http.js<br/>onError 拦截"]
Nav["navbar.ts"] --> Util["utils/ui.js<br/>douPageTo"]
Nav --> Env["utils/env.js<br/>isDebugEnv/isServerDebug"]
Nav --> WX["wx.* API"]
性能考量
- 减少 setData 频率:在 observer 中对数据进行合并后再 setData,避免频繁更新。
- 合理使用插槽:仅在需要时渲染复杂插槽内容,降低首屏压力。
- 条件渲染:通过 wx:if 控制调试入口等低频功能模块的渲染。
- 高度计算缓存:导航高度由应用层统一计算并写入 globalData,组件直接读取,避免重复计算。
故障排查指南
- 未授权统一登出:HTTP 拦截器捕获 UNAUTHORIZED 错误后调用 authStore.logout,检查登录态是否正确清除。
- 页面不存在:onPageNotFound 记录路径并提示,核对路由配置与页面路径拼写。
- 调试入口不响应:确认双门控条件(客户端非正式版 + 服务端调试模式)满足;检查 debug-layer 的 pointer-events 设置。
- 导航高度异常:检查 onLaunch 中的窗口与设备信息读取逻辑,确保 statusBarHeight、navigationBarHeight 正确赋值。
结论
通过在应用层统一初始化与在组件层明确 props、事件、插槽与生命周期,DouPHP 小程序实现了高内聚、低耦合的组件体系。navbar 组件展示了标准的配置与使用方式,可作为其他组件开发的参考模板。建议在后续开发中持续完善生命周期覆盖、事件透传与作用域插槽,以提升组件的可复用性与可维护性。
附录:完整示例与最佳实践
组件创建步骤
- 新建组件目录与文件:在 components 下创建组件文件夹,添加 .json/.ts/.wxml/.wxss。
- 声明组件:在 .json 中设置 "component": true。
- 定义属性:在 .ts 的 properties 中声明类型、默认值与观察者。
- 编写模板:在 .wxml 中使用插值、条件渲染与插槽。
- 实现方法:在 .ts 的 methods 中处理用户交互与路由跳转。
组件使用步骤
- 注册组件:在页面的 .json 中引用组件路径。
- 传入属性:在页面 WXML 中为组件设置 title、backgroundColor、titleColor、scrollOpacity、url、showMenu 等。
- 使用插槽:根据需要插入 left、center、right 插槽内容。
- 监听事件:如需自定义事件,可在组件 methods 中通过 triggerEvent 触发,并在页面中通过 bind:eventName 接收。
事件流程图(基于现有实现)
flowchart TD
Start(["用户点击"]) --> CheckUrl{"是否携带 url?"}
CheckUrl --> |是| DoPageTo["调用 douPageTo(url)"]
CheckUrl --> |否| DoBack["调用 wx.navigateBack()"]
DoPageTo --> End(["结束"])
DoBack --> End
最佳实践清单
- 属性:
- 明确类型与默认值,避免 undefined 导致渲染异常
- 使用 observer 做数据清洗与边界检查
- 事件:
- 对外暴露最小必要的事件集,避免过度耦合
- 事件参数保持简洁且语义清晰
- 插槽:
- 优先使用具名插槽提升可读性
- 谨慎暴露内部状态,必要时通过只读属性或作用域插槽
- 生命周期:
- 在 attached 中初始化轻量逻辑
- 在 detached 中释放资源
- 配置:
- 组件 JSON 仅保留必要开关
- 多插槽需在 options 中显式声明