简介
本文件面向 DouPHP 小程序的组件开发者,系统化说明小程序组件系统的架构设计、分类与职责、自定义组件开发规范(属性、事件、插槽、样式隔离)、生命周期与状态同步机制,并提供常用组件的使用示例、复用与扩展策略,以及测试与调试最佳实践。文档基于仓库中 miniprogram 目录下的实际实现进行梳理,确保内容可落地、可追溯。
项目结构
小程序工程位于 miniprogram 目录,包含默认主题 default 与企业主题 company 两套配置,二者均通过 app.json 注册页面与全局 usingComponents,并在 components 目录下提供可复用的基础组件。当前仓库已实现的组件包括:
- 导航栏组件 navbar:用于统一顶部导航、返回/首页按钮、标题与右侧插槽等能力。
- HTML 渲染组件 mp-html:第三方富文本渲染组件,支持图片预览、视频控制、锚点跳转等。
graph TB
A["小程序应用<br/>app.json"] --> B["页面层<br/>pages/*"]
A --> C["全局组件注册<br/>usingComponents"]
C --> D["导航栏组件<br/>components/navbar"]
C --> E["富文本组件<br/>components/mp-html"]
B --> D
B --> E
核心组件
- 导航栏组件(navbar)
- 职责:统一导航栏外观与交互,支持标题、背景色、标题色、滚动透明度、菜单显隐、左侧/中心/右侧插槽、返回与首页跳转、调试入口圆点。
- 关键特性:多插槽(left/center/right)、属性监听器更新内部标题、根据全局尺寸计算高度、条件渲染调试入口。
- 富文本组件(mp-html)
- 职责:将 HTML 字符串渲染为小程序节点树,提供图片预览、视频暂停、播放速率设置、锚点跳转、懒加载、复制链接等能力。
- 关键特性:content 属性变更自动解析渲染;提供 getText/getRect/navigateTo/pauseMedia 等方法;支持插件体系。
架构总览
小程序采用“页面 + 组件”的分层组织方式:
- 页面层(pages):承载业务视图与路由。
- 组件层(components):封装通用 UI 与交互逻辑,供页面复用。
- 全局配置(app.json):声明页面、全局窗口样式、TabBar、全局 usingComponents。
- 工具与服务(utils/services/stores):提供环境判断、UI 辅助、网络请求、状态管理等能力。
graph TB
subgraph "页面"
P1["首页"]
P2["商品详情"]
P3["订单列表"]
end
subgraph "组件"
N["navbar 导航栏"]
H["mp-html 富文本"]
end
subgraph "全局"
G["app.json<br/>usingComponents"]
end
G --> N
G --> H
P1 --> N
P2 --> N
P3 --> N
P2 --> H
P3 --> H
详细组件分析
导航栏组件(navbar)
- 组件定义与属性
- properties:title、backgroundColor、titleColor、scrollOpacity、url、showMenu。
- data:statusBarHeight、navigationBarHeight、menuButtonHeight 等由全局获取的尺寸信息;debugDot 用于调试入口显示。
- options:multipleSlots 启用多插槽。
- 生命周期
- lifetimes.attached:在组件实例被插入到页面节点树时执行,用于初始化调试入口可见性(双门控:客户端非正式版且服务端调试开启)。
- 方法与交互
- goBack:优先使用传入 url 跳转,否则返回上一页。
- goHome:跳转到首页 Tab。
- openDebug:进入调试页。
- 模板与插槽
- 左区:返回与首页按钮(受 showMenu 控制),以及 left 插槽。
- 中区:center 插槽未提供时回退到 title,颜色与透明度跟随属性。
- 右区:right 插槽。
- 背景层:opacity 随 scrollOpacity 变化,实现滚动渐变效果。
- 调试入口:全屏右侧固定圆点,跨视口存在以规避 fixed 子元素点击不响应问题。
sequenceDiagram
participant Page as "调用页面"
participant Nav as "navbar 组件"
participant WX as "微信API"
Page->>Nav : 渲染并传入 {title, backgroundColor, showMenu, url}
Nav->>Nav : attached() 初始化调试入口可见性
Page->>Nav : 用户点击返回
Nav->>Nav : goBack(e)
alt 存在 url
Nav->>WX : douPageTo(url)
else 不存在 url
Nav->>WX : navigateBack()
end
Page->>Nav : 用户点击首页
Nav->>WX : switchTab("/pages/index/index")
flowchart TD
Start(["组件挂载"]) --> CheckEnv{"是否满足调试入口条件?"}
CheckEnv --> |是| ShowDot["设置 debugDot = true"]
CheckEnv --> |否| HideDot["保持 debugDot = false"]
ShowDot --> End(["完成"])
HideDot --> End
富文本组件(mp-html)
- 组件定义与属性
- properties:containerStyle、content、copyLink、domain、errorImg、lazyLoad、loadingImg、pauseVideo、previewImg、scrollTable、selectable、setTitle、showImgMenu、tagStyle、useAnchor。
- data:nodes(渲染后的节点树)。
- 生命周期与钩子
- created:初始化插件数组。
- detached:触发 onDetached 钩子。
- 方法
- setContent:解析 content 并更新 nodes,触发 onLoad 与 ready 事件;支持增量更新。
- getRect:获取根节点矩形信息。
- pauseMedia:暂停所有媒体。
- setPlaybackRate:设置播放速率。
- navigateTo:根据 useAnchor 与选择器进行锚点滚动定位。
- getText:提取纯文本内容。
- 事件
- load:解析完成后触发。
- ready:布局就绪后触发,附带根节点尺寸。
sequenceDiagram
participant Page as "调用页面"
participant Html as "mp-html 组件"
participant Parser as "解析器"
participant WX as "微信API"
Page->>Html : 设置 content
Html->>Parser : parse(content)
Parser-->>Html : 节点树 nodes
Html->>Html : setData({nodes})
Html->>Page : 触发 load
Html->>Html : 计算根节点尺寸(getRect)
Html->>Page : 触发 ready(含尺寸)
Note over Html,Page : 支持 lazyLoad / previewImg / pauseVideo 等行为
依赖关系分析
- 组件注册
- 通过 app.json 的 usingComponents 将 navbar 全局注册,页面可直接使用 <navbar />。
- 组件内依赖
- navbar 依赖 utils/env 与 utils/ui,用于环境判断与页面跳转。
- mp-html 依赖内置解析器与微信小程序 API(SelectorQuery、pageScrollTo 等)。
- 页面与组件耦合
- 页面通过属性向组件注入数据,通过事件回调接收组件状态变化,降低耦合度。
graph LR
App["app.json<br/>usingComponents"] --> Navbar["navbar 组件"]
App --> MpHtml["mp-html 组件"]
Navbar --> Env["utils/env"]
Navbar --> UI["utils/ui"]
MpHtml --> WXAPI["wx.* API"]
性能考量
- 导航栏
- 使用 multipleSlots 减少重复 DOM,按需渲染 left/center/right 区域。
- 通过 scrollOpacity 控制背景透明度,避免重绘开销过大。
- 调试入口仅在满足条件时渲染,减少不必要的节点。
- 富文本
- 使用懒加载(lazyLoad)与占位图(loadingImg/errorImg)优化首屏渲染。
- 图片预览(previewImg)与视频控制(pauseVideo)按需启用,减少资源占用。
- 增量更新 nodes 提升大数据量场景下的渲染效率。
故障排查指南
- 导航栏
- 标题为空或类型异常:检查 properties.title 的 observer 分支,确保传入值被转换为字符串或清空。
- 返回行为不符合预期:确认传入 url 是否存在;若为空则默认返回上一页。
- 调试入口不显示:检查客户端环境与服务器端调试开关是否同时满足条件。
- 富文本
- 内容未渲染:确认 content 已正确赋值,并监听 load/ready 事件。
- 锚点跳转无效:确认 useAnchor 已启用,且目标节点存在。
- 媒体无法暂停:确认 pauseVideo 已启用,并通过 pauseMedia 方法调用。
结论
DouPHP 小程序组件系统以“页面 + 组件”为核心,通过 app.json 的全局 usingComponents 实现组件复用。当前已实现的 navbar 与 mp-html 分别覆盖导航与富文本两大高频场景,具备清晰的属性、事件、插槽与生命周期设计。遵循本文的开发规范与实践建议,可快速构建高质量、可维护的小程序界面。
附录
自定义组件开发规范
- 组件属性(properties)
- 明确类型与默认值,必要时提供 observer 处理值变更。
- 对可能为 null/undefined 的属性做防御性处理。
- 事件处理(events)
- 通过 triggerEvent 暴露必要事件(如 load、ready),便于父级监听。
- 事件参数尽量精简,仅传递必要数据。
- 插槽使用(slots)
- 合理使用多个插槽(left/center/right)提高灵活性。
- 提供合理的回退内容,保证无插槽时的可用性。
- 样式隔离
- 组件样式独立,避免污染页面;必要时通过类名与作用域控制。
- 使用 CSS 变量或内联样式动态控制主题与尺寸。
组件生命周期与状态同步
- 生命周期
- attached:组件插入时初始化(如调试入口可见性)。
- detached:组件移除时清理资源(如取消监听)。
- 状态同步
- 通过 properties 的 observer 同步外部状态到内部 data。
- 通过事件将内部状态变化通知父级,保持双向一致性。
常用组件使用示例
- 导航栏
- 在页面中使用 <navbar title="标题" backgroundColor="#fff" titleColor="#333" showMenu="{{true}}" url="/pages/xxx/xxx" />。
- 通过 left/center/right 插槽定制左右区域内容。
- 富文本
- 在页面中使用 <mp-html content="{{html}}" lazyLoad="{{true}}" previewImg="{{true}}" pauseVideo="{{true}}" />。
- 监听 load/ready 事件,获取渲染结果与尺寸。
组件复用与扩展
- 复用策略
- 将通用 UI 抽象为组件,通过属性与插槽组合不同形态。
- 通过全局 usingComponents 注册,减少引用成本。
- 扩展方法
- 为组件提供方法(如 navigateTo、pauseMedia),供页面调用。
- 通过事件与属性实现松耦合的数据流。
测试与调试最佳实践
- 单元测试
- 针对组件方法编写用例(如 goBack、setContent)。
- 验证属性变更与事件触发是否符合预期。
- 集成测试
- 在页面中组合多个组件,验证整体交互流程。
- 调试技巧
- 使用调试入口圆点快速进入调试页。
- 利用 console.log 与 wx.getSystemInfo 输出关键尺寸与环境信息。