必须使用 rich-text 组件实现跨平台搜索高亮,因其支持结构化节点渲染、规避 v-html 在安卓真机及厂商 ROM 的样式失效和解析问题,并需转义正则元字符、全局匹配、手动切片生成 nodes 数组,配合稳定 key 和显式样式控制字体、行高与对齐。

搜索关键词高亮必须用 rich-text,别用 v-html
安卓真机上 v-html 渲染 标签会直接忽略样式,尤其在 nvue 页面或某些厂商 ROM(如华为、小米)里,v-html 甚至不解析标签,只当纯文本显示。微信小程序虽支持 v-html,但存在 XSS 风险,且无法控制内联样式优先级。
rich-text 是 uni-app 唯一跨平台稳定支持富文本节点渲染的组件,它接受结构化节点数组,能精准控制每个片段的样式和语义。
- 节点格式必须是:
[{ name: 'text', attrs: { style: 'color:#e64340;' }, children: [{ type: 'text', text: '关键词' }] }] - 不能传字符串,也不能传带 HTML 标签的字符串——
rich-text不解析 HTML 字符串,只认节点对象 - 若传错格式(比如直接传
'xxx'),iOS 会白屏,Android 会静默失败
highlightText 函数要处理正则特殊字符和全量匹配
用户搜 1+1 或 price[0] 这类含正则元字符的词,不转义就会报错或漏匹配;另外,uni-app 场景下常见「标题中多次出现同一词」(如“苹果手机 苹果平板 苹果耳机”),只替换第一个就失去意义。
正确做法是先转义关键词,再用全局正则 + matchAll 或循环 indexOf 拆分文本段落,生成带 highLight 标记的对象数组。
- 转义函数必须包含:
escapeRegExp(keyword)→keyword.replace(/[.*+?^${}()|[]\]/g, '\$&') - 避免用
String.prototype.replace直接拼 HTML 字符串,那会破坏rich-text节点结构 - 推荐用
while (pos !== -1)手动切片,比正则matchAll在低端 Android 上更稳(V8 引擎兼容性问题)
订单列表渲染时,nodes 数据需响应式更新且 key 稳定
订单项通常是 v-for 循环渲染,如果只对 item.title 做高亮处理但没重置 nodes 数组引用,Vue 2(uni-app 默认)可能跳过更新,导致高亮滞后或失效。
- 每次搜索后,必须重新生成整个
nodes数组,不能复用旧引用 - 给
rich-text加:key="item.id + '_' + keyword",强制刷新,避免缓存节点 - 不要把高亮逻辑写在 computed 里依赖
item.title,computed 缓存会误判变化,应放在methods中显式调用
安卓端注意 rich-text 的字体继承和行高塌陷
订单标题常含多行文本(如 “iPhone 15 Pro 256G 深空黑 全网通”),rich-text 默认不继承父级 font-size 和 line-height,容易出现字号变小、文字挤在一起、高亮背景色断开等问题。
- 必须显式设置
rich-text的style:font-size: 28rpx; line-height: 40rpx; - 高亮文本的
style中加vertical-align: middle;,否则与周边文字基线不齐 - 避免在
rich-text外层套text或view并设flex,部分安卓机型会截断最后一行
订单搜索高亮真正难的不是匹配逻辑,而是节点生成后如何让 rich-text 在所有安卓机型上保持一致渲染——字体、行高、背景色高度、换行对齐,这些细节不测真机根本发现不了。











