文章目录
-
-
- 前言
- 富文本需求场景
- RichText 组件
- 支持的 HTML 标签
- Web 渲染复杂 HTML
- 两种方案对比
- 图片点击处理
- 写在最后
-
前言

后端扔过来一段 HTML,让我在 App 里展示。我一上来就用 Text 组件硬拼 Span,拼到第三个标签人就崩了——这得拼到猴年马月?
后来发现 HarmonyOS7 有专门的富文本渲染方案。今天聊聊两种主流方式:RichText 组件和 Web 组件,帮你根据场景选对路子。 富文本渲染是内容型 App 的刚需。新闻详情、公告说明、商品描述……后端返回的几乎都是 HTML。前端要做的事就一件:把 HTML 渲染成好看的 UI。
听起来简单,但坑不少:标签支持不全、图片点击没反应、样式跟原生不一致……选错方案,后面全是补丁。
富文本需求场景
不同场景对富文本的要求差异很大:
| 用户协议 / 隐私政策 | 简单(p/a/b 标签为主) | 无 | RichText |
| 新闻详情 | 中等(图文混排) | 图片点击放大 | RichText |

| 活动页 / 营销页 | 复杂(CSS 动画+JS 交互) | 高 | Web | | 第三方网页嵌入 | 不可控 | 全交互 | Web |
简单总结:内容为主用 RichText,交互为主用 Web。
RichText 组件
RichText 是 HarmonyOS7 专门为 HTML 内容渲染设计的组件,用法简单粗暴——直接把 HTML 字符串塞进去:
@Entry
@Component
struct RichTextDemo {
private htmlContent: string = `
<h2>HarmonyOS7 更新公告</h2>
<p>本次更新带来了<strong>全新的 ArkUI 组件</strong>,性能提升显著。</p>
<ul>
<li>新增 Flex 弹性布局组件</li>
<li>优化 List 滚动性能</li>
<li>修复已知 <em>50+</em> 问题</li>
</ul>
<p>详细内容请访问<a href="https://developer.huawei.com">开发者官网</a>。</p>
`
build() {
Scroll() {
Column() {
RichText(this.htmlContent)
.width('100%')
.padding(16)
.onReady(() => {
console.info('RichText 渲染完成')
})
}
}
.width('100%')
.height('100%')
}
}

关键代码讲解:
- RichText(this.htmlContent) —— 直接传入 HTML 字符串,组件自动解析渲染
- .onReady() —— 渲染完成的回调,可以在这里做后续处理(比如图片加载后的高度调整)
- RichText 只支持通用属性中的 width、height、size、layoutWeight,不能设 fontSize、fontColor 这些文本属性——因为样式由 HTML 标签控制
RichText 的样式完全由 HTML 内联决定,想改字号得在 HTML 里写 <span style="font-size:18px">。
支持的 HTML 标签
RichText 不是啥 HTML 标签都支持,以下是常用标签的支持情况:
| <h1>~<h6> | 标题 | <h2>标题</h2> |
| <p> | 段落 | <p>内容</p> |
| <a> | 超链接 | <a href="url">链接</a> |
| <strong> / <b> | 加粗 | <b>加粗</b> |
| <em> / <i> | 斜体 | <i>斜体</i> |
| <u> | 下划线 | <u>下划线</u> |
| <s> | 删除线 | <s>删除</s> |
| <ul> / <ol> | 列表 | <ul><li>项</li></ul> |
| <img> | 图片 | <img src="url"> |
| <table> | 表格 | <table><tr><td>…</td></tr></table> |
| <div> / <span> | 容器 | <div style="…">…</div> |
| <br> | 换行 | <br> |
| <hr> | 分割线 | <hr> |
不支持的标签会被直接忽略,不会报错也不会显示。所以用之前先确认你的 HTML 里有没有奇奇怪怪的标签。
Web 渲染复杂 HTML
当 HTML 包含复杂 CSS、JavaScript 或者 RichText 不支持的标签时,就得用 Web 组件了:
import webview from '@ohos.web.webview'
@Entry
@Component
struct WebRichTextDemo {
private webController: webview.WebviewController = new webview.WebviewController()
private htmlContent: string = `
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
body { margin: 0; padding: 16px; font-family: sans-serif; color: #333; }
h2 { color: #007DFF; }
.highlight { background: linear-gradient(120deg, #f6d365 0%, #fda085 100%);
padding: 4px 8px; border-radius: 4px; }
.card { background: #f8f8f8; border-radius: 12px; padding: 16px; margin: 12px 0; }
img { max-width: 100%; border-radius: 8px; }
</style>
</head>
<body>
<h2>限时活动</h2>
<div class="card">
<p>活动期间,<span class="highlight">全场商品8折</span>!</p>
<img src="https://example.com/banner.jpg" onclick="onImageClick(this.src)">
</div>
<script>
function onImageClick(src) {
window.postMessage(JSON.stringify({type:'imageClick', src: src}));
}
</script>
</body>
</html>
`
build() {
Column() {
Web({ src: '', controller: this.webController })
.width('100%')
.layoutWeight(1)
.javaScriptAccess(true)
.domStorageAccess(true)
.onPageEnd(() => {
this.webController.loadData(
this.htmlContent,
'text/html',
'UTF-8'
)
})
.onMessage((event) => {
let data = JSON.parse(event.data as string)
if (data.type === 'imageClick') {
console.info(`图片被点击: ${data.src}`)
}
})
}
.width('100%')
.height('100%')
}
}
关键代码讲解:
- javaScriptAccess(true) —— 必须开启,不然 <script> 里的代码不执行
- domStorageAccess(true) —— 开启 DOM 存储,某些 HTML 依赖 localStorage
- loadData() —— 加载 HTML 字符串,三个参数分别是内容、MIME 类型、编码
- onMessage() —— 接收 HTML 里 window.postMessage() 发送的消息,这是 Web 和原生通信的桥梁
- onPageEnd() —— 页面加载完成时触发,在这里注入 HTML 内容比较稳妥
Web 组件嵌套在 Scroll 里时,别忘了加 .nestedScroll() 处理滚动冲突。
两种方案对比
| 渲染性能 | 高(原生渲染) | 低(WebView 引擎) |
| HTML 支持度 | 有限(基础标签) | 完整(含 CSS/JS) |
| 交互能力 | 仅链接点击 | 完整 JS 交互 |
| 内存占用 | 低 | 高 |
| 样式控制 | 受限(只支持4个通用属性) | 灵活(CSS 全支持) |
| 与原生通信 | onReady 回调 | postMessage 双向通信 |
| 加载速度 | 快 | 慢(需初始化引擎) |
图片点击处理
RichText 里的图片点击是个常见需求,可惜 RichText 本身没有直接提供图片点击回调。变通方案:
方案一:用 onReady + 正则替换
build() {
RichText(this.processHtml(this.htmlContent))
.width('100%')
.padding(16)
}
processHtml(html: string): string {
return html.replace(
/<img\\s+src="([^"]*)"/g,
'<img src="$1" onclick="window.open(\\'$1\\')"'
)
}
方案二:直接用 Web 组件
如果图片点击交互比较复杂(比如要弹出预览、左右滑动),老老实实用 Web + postMessage,别折腾了。
写在最后
选方案的核心判断:HTML 有没有 CSS 动画或 JS 交互?
- 没有 → RichText,轻快省
- 有 → Web,别犹豫
别想着用 RichText 硬撑复杂 HTML,后期补丁比重写还痛苦。也别啥都用 Web,一个简单的用户协议页加个 WebView,内存占用直接翻倍。
选对工具,事半功倍。
![[项目] --- 基于 Spring Boot + Redis的多设计模式抽奖系统-171主机测评](https://www.171host.com/wp-content/uploads/2026/11/20261031220757-6ae666bdaa3f5-220x150.png)