23 KiB
H5 原型 → 微信小程序迁移桥接规范(可执行版 v2.0)
适用对象:人工开发、AI 批量迁移、代码审查、验收回归
适用范围:本项目上传的 H5 原型页面、配套 CSS/JS、静态资源
目标:在微信原生小程序中实现页面与交互的高还原迁移;除字体渲染细微差异外,样式、层级、动效、状态切换、页面流转尽量 1:1 对齐 H5 验收原型
1. 文档定位
这不是知识笔记,而是执行规程。
使用本规范时,AI 或开发者必须做到:
- 能从单个 H5 页面产出对应的小程序页面文件。
- 能明确哪些能力可直接迁移,哪些必须降级,哪些禁止直迁。
- 能在不使用 DOM API 的前提下,把 H5 交互改造成小程序的数据驱动实现。
- 能输出可交付物,而不是停留在“分析建议”。
本规范优先级高于旧版桥接文档。若旧版文档与本规范冲突,以本规范为准。
2. 项目级输入与输出契约
2.1 输入物
单页迁移时,输入物必须至少包含:
- 对应 H5 页面 HTML 文件
- 该页面引用的 CSS(页面内
<style>、独立 css 文件、Tailwind utility) - 该页面引用的 JS
- 该页面依赖的图片 / 图标 / SVG / JSON Mock
- 页面跳转关系和入口参数
2.2 输出物
每个页面迁移后,必须至少产出:
pages/<route>/<route>.wxmlpages/<route>/<route>.wxsspages/<route>/<route>.jspages/<route>/<route>.json- 该页面使用到的 mock 数据文件或页面内 mock 常量
- 迁移说明(至少包含:状态变量、事件、待确认项、降级项)
2.3 不允许的输出
以下结果视为未完成:
- 只给“迁移思路”,不产出页面文件
- 只把 Tailwind class 翻译成 CSS,不改 WXML / 交互
- 继续依赖
document.*、window.*、history.*、localStorage等浏览器 API - 以“兼容性未知”为由保留 H5 写法不处理
- 把高风险 CSS 特性原样搬过去,且不写降级方案
3. 项目级强制决策
3.1 框架与运行时
- 必须使用微信原生小程序页面体系:WXML + WXSS + JS + JSON。
- 禁止继续在小程序端运行 Tailwind CDN / 浏览器脚本。
- 禁止使用 DOM 驱动交互。 页面必须改为数据驱动。
- 不引入 Taro / uni-app / WebView 兜底。 本规范面向原生小程序页面迁移。
3.2 验收基准
- H5 原型的主要验收基准宽度为 412 CSS px。
- 小程序以 412 宽设备的视觉效果为主验收目标。
- 其他常见宽度设备允许比例差异,但不得出现:文本溢出、遮挡、错层、关键按钮点击区域异常、吸顶/弹层错位。
3.3 单位策略
采用 rpx 为主、px 为辅 的混合单位方案。
- 优先
rpx:页面宽度、横向布局、卡片尺寸、主容器 padding / margin、列表间距、栅格、吸顶区高度。 - 优先
px:1px 发丝线、阴影 blur/spread、小图标、绝对定位微调、小控件尺寸、状态栏 / 安全区补偿、细描边。 - 按效果决定:字号、圆角、局部 padding、某些 transform 位移。
换算基准:
rpx = H5_CSS_px × (750 / 412)
≈ H5_CSS_px × 1.8204
默认规则:
- 普通布局值:四舍五入到整数
rpx - 视觉敏感值:允许人工微调,不强行套公式
- 不使用“统一取偶数 rpx”的硬规则
3.4 页面滚动策略
- 默认使用 页面自然滚动。
- 只有在必须做局部滚动区域时,才使用
scroll-view。 - 吸顶、滚动联动、section 感知优先围绕页面滚动实现;不要无必要把整页包进
scroll-view。
3.5 样式组织策略
- 全局 token、复用组件样式放
app.wxss或公共样式文件。 - 页面私有样式放页面同名
.wxss。 - 样式优先使用 class,动态值用内联 style 绑定。
- 不以 CSS 变量作为唯一运行前提;优先输出静态色值 / 静态 token。若项目后续验证 CSS 变量稳定可用,可作为增强层,不可作为唯一实现路径。
3.6 文本与行高策略 ⚠️
关键发现:微信小程序的 <text> 组件不能直接设置 line-height,必须通过外层 <view> 设置。
全局设置(推荐):
page {
line-height: 1.5; /* Tailwind 默认行高 */
}
view {
line-height: inherit; /* view 继承 page 的 line-height */
}
/* text 会自动继承外层 view 的 line-height,不需要额外设置 */
局部覆盖:
.section-title {
font-size: 26rpx;
line-height: 36rpx; /* 在 view 的 class 上设置,text 会继承 */
font-weight: 600;
}
错误做法:
/* ❌ 直接在 text 上设置 line-height 无效 */
text {
line-height: 36rpx; /* 不会生效 */
}
执行规则:
- 所有文本类样式必须同时设置
font-size和line-height line-height必须在外层<view>的 class 上设置,不能在<text>上设置- 标准字号的
line-height换算参考附录 B.3 - 若发现 Y 轴高度与 H5 端不一致,优先检查
line-height是否正确设置
3.7 SVG / 图标策略
- 禁止把 H5 的内联
<svg>...</svg>直接当 WXML DOM 搬运。 - 资源层允许
svg文件进入小程序项目包,但页面显示是否稳定,必须以目标设备实测为准。 - 默认执行顺序:
- 简单静态图标:优先导出为独立资源文件
- 若
svg渲染不稳定:转为png - 高频单色图标:允许改为 iconfont / 组件化图标
- 动态换色的 SVG 不要临时拼接字符串;应改为多份资源、图标组件或样式控制的等价实现。
4. 技术基线与能力分级
说明:本规范不把“经验上可能可用”的能力写成“完全支持”。 所有能力分三类:A 可直接用,B 有条件使用,C 禁止直迁。
4.1 A 类:可直接使用
以下能力在当前项目中视为稳定迁移能力:
app.wxss/ 页面wxss/@importrpx.class、#id、元素选择器、::before、::afterflex、position: relative/absolute/fixedbox-shadow、border-radius、linear-gradientopacity、常规transformtransition、animation- 动态内联样式绑定
onPageScrollwx.createAnimation()wx.createSelectorQuery()wx.createIntersectionObserver()navigator/wx.navigateTo/wx.redirectTo/wx.switchTab/wx.navigateBackview/navigator的hover-class
4.2 B 类:有条件使用,必须带回退或验证
以下能力允许使用,但不能把它们当成项目硬依赖:
position: stickygridfilter: blur()backdrop-filterclip-pathvhline-clamp- 复杂组合选择器
- 资源型
svg - CSS 变量
执行规则:
- 使用前必须确认该页面已有回退方案。
- 若页面对视觉或交互依赖度高,则必须做真机验证。
- 若 B 类能力失效,不得阻塞交付,必须切换为本规范定义的降级实现。
4.3 C 类:禁止直迁
以下能力不得原样从 H5 搬到小程序:
document.getElementById/querySelector/querySelectorAllclassList.add/remove/toggle- 直接改
element.style.xxx innerHTML/textContent方式渲染视图window.scrollY/window.scrollTohistory.backlocalStorage/sessionStoragealert/confirm- CSS
env(safe-area-inset-*) :hover/group-hover:*- 依赖浏览器焦点模型的
:focus/:active交互 - 依赖
:first-child/:last-child/:nth-child才能成立的视觉规则
5. 页面转换的标准执行流程
每迁移 1 个页面,都必须按以下顺序执行。
步骤 1:页面资产盘点
输入:HTML / CSS / JS / 图片资源
动作:
- 抽取页面标题、路由名、入口参数、返回路径
- 列出页面块:顶部、卡片区、列表区、底部操作区、弹层、浮层、Toast
- 列出页面状态:默认态、空态、加载态、错误态、选中态、展开态、禁用态
- 列出页面动效:淡入、位移、缩放、吸顶、滚动联动、长按、评分拖动
输出:页面迁移卡
步骤 2:结构改写为 WXML 语义树
动作:
div→view- 文本优先用
text - 图片用
image - 链接/跳转用
navigator或bindtap - 表单元素替换为原生小程序组件
- 列表一律改为
wx:for - 条件显示一律改为
wx:if/hidden/ 条件 class
禁止:
- 保留 H5 DOM 层级只是把标签名替换一下
- 在
text内嵌套view - 用字符串拼接 HTML 片段
步骤 3:Tailwind 与自定义 CSS 拆解
动作:
- 先按视觉功能拆成:布局、尺寸、文本、颜色、装饰、状态、动画
- 再判断每个值使用
rpx还是px - 统一抽出公共 token,不允许每页各自发散命名
要求:
- 不保留“一长串 utility class 直接照搬”的中间态
- 对频繁出现的组合样式抽成语义类,如
.card、.section-title、.tab--active
步骤 4:交互从 DOM 驱动改为数据驱动
动作:
- 把所有 DOM 查询改成状态变量
- 把显隐、激活、展开、选中、校验、加载都改成
data驱动 - 把滚动联动改成
onPageScroll+ 节流 + 仅在状态变化时setData
输出:状态表
状态表至少包含:
- 状态变量名
- 默认值
- 可选值
- 受哪个事件修改
- 影响哪些视图
步骤 5:页面级动效实现
执行规则:
- 纯显隐 / 透明度 / 位移 / 简单位移动画:优先
transition/animation - 需要顺序编排、组合变换、受事件精确驱动:用
wx.createAnimation() - 高频交互不要每帧
setData
步骤 6:导航与参数改造
动作:
- 普通页面:
wx.navigateTo - 替换当前页:
wx.redirectTo - tabBar 页面:
wx.switchTab - 返回:
wx.navigateBack - 页面参数:统一在
onLoad(query)中读取
步骤 7:安全区与导航栏补偿
动作:
- 禁止使用
env(safe-area-inset-*) - 通过系统信息计算状态栏与底部安全区
- 自定义导航栏页面必须统一实现,不得一页一套
步骤 8:Mock 数据接入
动作:
- 页面先用 mock 跑通
- 模板静态文案与后端数据字段分开
- 所有列表、徽标、状态标签都要有 mock
步骤 9:真机回归与像素微调
动作:
- 先看 412 宽主验收设备
- 再看至少一台 375 宽设备
- 出现不对齐时优先微调局部
px/rpx,不要推翻整体单位策略
步骤 10:记录迁移说明
每页必须输出迁移说明,至少包含:
- 页面依赖资源
- 迁移状态变量
- 高风险点
- 已做降级项
- 待后端对接字段
- 待真机复核项
6. Tailwind → WXSS 的执行规则
6.1 间距与尺寸
执行原则:
- 标准 spacing 先换算为 H5 实际 px,再决定
rpx/px。 - 主容器、卡片、列表间距优先
rpx。 - 图标、徽标、定位补偿优先
px。 - arbitrary 值不能偷懒统一换
rpx,必须逐项判断。
建议 token(412 基准)
| H5 px | 建议值 |
|---|---|
| 4px | 8rpx |
| 8px | 14rpx |
| 12px | 22rpx |
| 16px | 29~30rpx |
| 20px | 36rpx |
| 24px | 44rpx |
| 32px | 58rpx |
| 40px | 72rpx |
说明:
- 16px 允许落在 29rpx 或 30rpx,以真机比对为准。
- 阴影参数不要强制
rpx化;优先保留px质感。
6.2 文本
标准字号类
对 Tailwind 标准字号类,迁移时应同时输出 font-size 与 line-height。
arbitrary 字号
规则:
text-[Npx]不能直接假设其 line-height = 1.2 倍字号。- 若原型页面显式设置了
leading-*,以显式值为准。 - 若未显式设置,则应从原型的实际计算样式、截图观感或上下文排版需求确定行高。
- 对单行标签/徽章文字,可使用更紧的 line-height;对正文、说明文必须按真实视觉高度定。
禁止:
- 在全项目层面硬编码“所有 arbitrary 字号默认 1.2 倍行高”
6.3 颜色
执行原则:
- 颜色优先输出静态十六进制 /
rgba()。 - Tailwind 透明度修饰符转成
rgba()。 - 若项目后续统一做 token 化,可再抽公共常量;首轮迁移不要把颜色系统设计复杂化。
6.4 布局
Flex
默认首选。能用 flex 做出来的布局,不优先上 grid。
Grid
仅在以下条件同时满足时允许:
- 页面是规则网格
- 列数固定
- 没有复杂跨列
- 真机验证通过
否则改用 flex + wrap + 固定宽度 / 百分比。
6.5 组合类
以下 Tailwind 组合迁移时不要机械翻译:
space-y-*divide-ygroup-hover:*peer-*hover:*focus:*active:*
迁移规则:
space-y-*:优先给循环项单独 class;选择器方案仅作受控场景补充divide-y:优先对列表项显式加边线 class,并根据 index 控首项hover:*:改hover-class或按压反馈focus:*:用bindfocus/bindblur+ 状态 class
7. HTML / 事件 / API 的标准映射
7.1 标签映射
| H5 | 小程序 |
|---|---|
div |
view |
span |
text |
p |
view / text |
img |
image |
a |
navigator / view bindtap |
button |
button / view bindtap |
input |
input |
textarea |
textarea |
ul/ol/li |
view + wx:for |
select |
picker |
补充规则:
image的mode必须按原图展示意图设置,不允许默认留空就交付。object-fit: cover常映射为aspectFill;但若原图不能被裁切,则应改为aspectFit。
7.2 事件映射
| H5 | 小程序 |
|---|---|
onclick |
bindtap |
oninput |
bindinput |
onchange |
bindchange |
onscroll |
bindscroll / onPageScroll |
ontouchstart |
bindtouchstart |
ontouchmove |
bindtouchmove |
ontouchend |
bindtouchend |
oncontextmenu |
bindlongpress |
注意:这只是常见替换,不代表浏览器事件语义与小程序事件语义完全等价。
7.3 冒泡与阻断
bind*:正常冒泡catch*:阻止事件向上冒泡
弹层、蒙层、内部内容区必须明确设计谁冒泡、谁拦截,不能边做边猜。
7.4 常见浏览器 API 替代
| H5 | 小程序 |
|---|---|
history.back() |
wx.navigateBack() |
window.location.href |
wx.navigateTo() |
window.location.replace |
wx.redirectTo() |
| tab 页跳转 | wx.switchTab() |
window.scrollY |
onPageScroll().scrollTop |
navigator.clipboard.writeText |
wx.setClipboardData() |
localStorage |
wx.setStorageSync/getStorageSync |
alert/confirm |
wx.showToast/wx.showModal |
8. JS 交互模式的标准改写
8.1 显隐切换
H5 的 classList.add/remove('hidden') 一律改为:
wx:if- 或
hidden - 或状态 class
默认建议:
- 大块弹层:
wx:if - 仅做过渡且结构稳定:状态 class + transition
8.2 Tab / 选中态
统一改为单一状态变量:
Page({
data: { activeTab: 'basic' },
onTabChange(e) {
this.setData({ activeTab: e.currentTarget.dataset.tab })
}
})
禁止:
- 同时维护多个布尔值表示同一个 tab 组选中态
8.3 展开 / 收起
统一改为对象映射或数组项状态,不允许操作 DOM 文本改按钮文案。
8.4 滚动联动
执行规则:
onPageScroll只在确实需要时声明。- 必须节流或去抖。
- 只在状态变化时
setData。 - 吸顶标题、目录高亮、section 感知,优先用
IntersectionObserver。
8.5 长按菜单
原型中的“卡片旁锚点弹出菜单”在小程序中优先改为:
- 底部 action sheet
- 或固定底部操作面板
原因:
- 更稳定
- 更易复用
- 更符合触屏交互
8.6 评分拖动 / 拖拽类交互
规则:
- 触摸起始时缓存容器 rect。
touchmove中仅基于缓存坐标计算,不每次重新 query。- 评分变化只在值变化时更新。
8.7 Toast / 短提示
优先级:
- 系统
wx.showToast - 若原型要求强定制视觉,再做自定义 toast 组件
8.8 动画
优先级:
- WXSS transition / animation
wx.createAnimation()- 避免高频
setData驱动逐帧动画
9. 高风险能力的强制降级规则
9.1 sticky
执行顺序:
- 页面自然滚动场景:先尝试
position: sticky - 若在
scroll-view中:不要硬上 sticky,改为滚动监听/观察者驱动 - 多层 sticky:只保留最外层 sticky
9.2 backdrop-filter
规则:
- 不作为交付必需能力
- 默认必须提供半透明背景降级
- 若失效,不得阻塞上线
9.3 vh
规则:
- 不把
100vh当成万能全屏高度 - 涉及自定义导航栏、安全区、底部操作栏的页面,必须计算可用高度
- 能用
min-height+ 内边距解决的,不强依赖vh
9.4 复杂选择器
规则:
- WXSS 公开支持的基础选择器以
.class、#id、元素、::before/::after为准 - 组合选择器只在局部受控场景下使用
- 不把复杂结构选择器写成项目标准手段
9.5 CSS 变量
规则:
- 首轮迁移不强制依赖
var() - 颜色、渐变、阴影优先输出静态值
- 若后续项目验证 CSS 变量稳定可用,可作为增强重构项,不是首轮交付阻塞项
10. 模板内容与数据内容的边界
每个页面都要把内容拆成三类:
10.1 模板固化内容
这些通常写死在页面模板或常量里:
- 页面标题
- 分区标题
- 固定按钮文案
- 空态文案
- Tooltip 固定说明
- 表头 / 标签名
10.2 Mock / 后端数据内容
这些必须抽成数据:
- 卡片列表
- 客户信息
- 任务信息
- 看板统计值
- 徽标状态
- 提示数量
- 聊天记录
- 备注内容
- 评分值
- 时间轴 / 历史记录
10.3 前端派生内容
这些应由前端根据后端字段计算:
- 状态色 class
- 选中态 class
- 进度条宽度
- 文案格式化
- 百分比显示
- 数字千分位
- 是否显示空态 / 加载态 / 错误态
11. 页面目录与公共层建议结构
app.js
app.json
app.wxss
/common
/styles
tokens.wxss
mixins.wxss
animation.wxss
/utils
format.js
system.js
nav.js
/mock
xxx.js
/components
app-navbar/
app-tab/
app-card/
app-empty/
app-toast/
app-action-sheet/
/pages
/task-list
/task-detail
/board-finance
/board-customer
/board-coach
/notes
/chat
...
/assets
/images
/icons
执行要求:
- 可复用的组件必须抽离
- 不允许把每页都做成孤岛
- 但也禁止首轮过度抽象,影响交付速度
12. 每页迁移完成的验收清单
以下清单必须全部勾过,页面才算完成。
12.1 结构
- 页面可正常进入
- 路由与参数正确
- 结构层级与原型一致
- 图片、图标、背景都已替换到位
12.2 样式
- 主布局宽度、边距、卡片尺寸与原型接近
- 文本字号、行高、字重合理
- 圆角、边框、阴影、渐变已还原
- 吸顶、弹层、底栏无错位
- 412 宽设备通过视觉验收
12.3 交互
- 点击反馈存在
- tab 切换正确
- 弹层开关正确
- 长按 / 复制 / 展开 / 收起 / 评分等交互正确
- 返回和跳转链路正确
12.4 性能
- 滚动时无明显抖动
- 没有在高频事件中无脑
setData - 动画不依赖逐帧 JS
12.5 风险项
- 所有降级项已记录
- 所有待真机复核项已记录
- 所有待接口对接字段已记录
13. AI 执行模板(标准提示词契约)
以下模板用于驱动 AI 按页迁移。
你现在负责把指定 H5 页面迁移为微信原生小程序页面。
必须遵守以下约束:
1. 输出原生小程序文件:wxml / wxss / js / json。
2. 禁止使用任何 DOM API、window、history、localStorage。
3. 禁止继续依赖 Tailwind 运行时;需将 Tailwind 与页面自定义样式改写为可维护的 WXSS。
4. 视觉目标是最大程度还原 H5;默认以 412 宽设备为验收基准。
5. 单位策略为 rpx 为主、px 为辅:布局主尺寸优先 rpx,发丝线/小图标/阴影/绝对定位微调优先 px。
6. 所有交互必须改为数据驱动。
7. 对 sticky / backdrop-filter / svg / vh / grid 等高风险能力,必须给出降级或验证说明。
8. 每输出一个页面,必须附带:
- 页面状态变量表
- 事件处理函数表
- mock 数据结构
- 未决问题与降级项
请按以下顺序输出:
A. 页面迁移摘要
B. 目录结构
C. WXML
D. WXSS
E. JS
F. JSON
G. mock 数据
H. 迁移说明与风险项
13.1 AI 页面状态表模板
| 状态变量 | 类型 | 默认值 | 可选值 | 影响视图 | 触发事件 |
|---|---|---:|---|---|---|
| showFilter | boolean | false | true/false | 筛选面板 | onToggleFilter |
| activeTab | string | overview | overview/detail/... | tab内容区 | onTabChange |
13.2 AI 风险项模板
- 已降级:backdrop-filter 改为半透明背景
- 待验证:顶部 sticky 在真机 Android 上需复核
- 待后端:客户列表、统计卡片、备注列表当前仍为 mock
14. 本项目对旧版桥接文档的修订结论
旧版文档可继续参考,但以下内容不再作为硬规范:
- 不再把大量现代 CSS 特性写成“完全支持”。
- 不再把 arbitrary 字号 line-height 的经验值当成定理。
- 不再把 CSS 变量当成首轮必选依赖。
- 不再把
.parent > view + view这类技巧写成唯一实现方案。 - 不再把
<image src="xxx.svg">写成无条件可靠方案。 - 不再允许“先翻样式,交互以后再说”的半迁移状态作为交付完成。
15. 参考文档(执行时必须优先查官方)
微信小程序官方 / 腾讯云镜像:
- WXSS 样式:https://www.tencentcloud.com/zh/document/product/1219/60346
- 页面与
onPageScroll:https://www.tencentcloud.com/zh/document/product/1219/61713 - 渲染层 / 事件模型:https://www.tencentcloud.com/zh/document/product/1219/61744
createSelectorQuery/createIntersectionObserver:https://www.tencentcloud.com/document/product/1219/57688- 动画
wx.createAnimation:https://www.tencentcloud.com/zh/document/product/1219/57764 - 视图容器
view/hover-class:https://www.tencentcloud.com/zh/document/product/1219/57773 - 导航组件
navigator:https://www.tencentcloud.com/zh/document/product/1219/57779 - 小程序目录结构与可上传文件类型:https://www.tencentcloud.com/zh/document/product/1219/57660
Tailwind 官方:
- Font Size:https://v3.tailwindcss.com/docs/font-size
- Line Height:https://v3.tailwindcss.com/docs/line-height
- Height:https://v3.tailwindcss.com/docs/height
16. 最终执行口径
本项目的小程序迁移,不是“把 Tailwind 翻译成 WXSS”这么简单。
真正的执行标准是:
- 页面结构重写为 WXML;
- 样式收敛为可维护的 WXSS;
- 交互全部改为小程序数据驱动;
- 对高风险 CSS 特性提供可交付降级;
- 每页都有 mock、状态表、事件表、风险说明和验收清单。
能做到这 5 条,才算“可执行版桥接规范”。