资讯类产品的详情页往往来自一份富文本内容。Web 页面中可以将经过安全处理的 HTML 放入页面进行展示,但小程序的运行环境与浏览器 DOM 不同,不能简单假定任意 HTML、样式和交互都可以直接复用。
文章详情页真正要解决的是一条转换链路:服务端内容如何进入小程序节点体系,正文中的图片和图集如何继续保持可交互,以及遇到不支持的结构时如何可靠降级。
先限定内容能力而不是追求完整 HTML
资讯正文常见元素相对有限:
段落、换行、标题、加粗文本普通图片、图片说明、图集引用、列表、链接视频或其他扩展媒体
如果一开始目标就是还原浏览器的全部 HTML 能力,实现会很容易失控。更合理的方式是先定义文章协议支持的节点类型,再将原始内容转换到这个协议上:
const nodes = [ { type: "paragraph", children: [{ type: "text", value: "车辆外观..." }] }, { type: "image", src: "https://img.example.com/car.jpg", width: 750 }, { type: "gallery", images: [ "https://img.example.com/1.jpg", "https://img.example.com/2.jpg" ] }];
页面不再承担解析任意字符串的责任,而是负责渲染有限且稳定的数据类型。
HTML 需要经过解析和转换
如果上游仍然提供 HTML,可以通过解析器生成语法树,再对白名单节点执行转换:
function transformNode(node) { if (node.name === "p") { return { type: "paragraph", children: transformChildren(node.children) }; } if (node.name === "img") { return { type: "image", src: normalizeImageUrl(node.attribs.src), alt: node.attribs.alt || "" }; } if (node.name === "strong") { return { type: "strong", children: transformChildren(node.children) }; } return transformChildren(node.children || []);}
这里最重要的不是代码长短,而是白名单边界。脚本、未知内联样式和难以支持的标签不应直接进入渲染结果。对于不认识的容器结构,可以尽量保留内部文本,避免整段正文丢失。
图片不是普通文本节点
正文中的图片通常还需要承担额外交互:
- 根据设备宽度计算展示尺寸。
- 图片加载前显示占位,加载失败时提供兜底。
- 点击图片时进入预览模式。
- 同一文章的所有正文图片可作为可滑动图集浏览。
在解析阶段可以同步收集图片列表:
function collectImages(nodes) { return nodes .filter(node => node.type === "image") .map(node => node.src);}function previewImage(current, images) { wx.previewImage({ current, urls: images });}
渲染一个图片节点时绑定当前地址和完整图集,正文中的普通插图就能够自然获得查看大图和左右切换能力。
图集应当成为独立内容节点
有些文章的图片本身是一组内容,例如车辆内饰细节或现场图集。它和正文中偶尔出现的一张配图不完全一样,往往需要展示数量、当前索引或一个明显的浏览入口。
因此图集不适合在模板里临时猜测,可以在内容协议中独立表示:
function ArticleNode({ node, articleImages }) { switch (node.type) { case "paragraph": return <RichText nodes={node.children} />; case "image": return ( <Image src={node.src} onClick={() => previewImage(node.src, articleImages)} /> ); case "gallery": return <Gallery images={node.images} />; default: return null; }}
这样后续对图集加入封面、页数或加载策略时,不会污染普通图片渲染逻辑。
转换放在哪里需要衡量
HTML 到节点协议的转换可以放在服务端,也可以放在小程序端。
服务端转换的优势是多个终端可共享内容处理结果,小程序首屏工作更少,也更容易统一内容安全规则。客户端转换便于快速调整展示策略,但会增加包体、计算成本和版本间结果差异。
对于内容类型稳定、访问量较大的资讯详情页,更倾向于让服务端输出适合终端消费的结构化结果,小程序保留少量展示适配和异常兜底。
详情页的质量取决于异常内容
真实文章中总会出现缺少尺寸的图片、失效链接、不支持的标签或内容数据不完整。详情页不能因为一张图解析失败就中断整篇文章渲染。
可以为每种节点准备降级策略:
未知文字容器 -> 保留纯文本图片加载失败 -> 显示失败占位,不影响后续段落空图集 -> 不展示模块不支持媒体 -> 展示可点击的来源链接或占位提示
资讯详情页看起来是内容展示,实际上包含内容协议、节点转换、图片交互和异常容错。把富文本先转换成受控的节点模型,页面才有能力持续扩展,而不会被任意 HTML 结构牵着走。