鸿蒙 uni-app x text组件避坑:样式不继承与空格处理
在 uni-app x 的鸿蒙平台开发中,text 组件看起来最简单,实际是高频踩坑点。尤其从 Web 转过来的开发者,习惯在 view 里直接写文字,但在 uni-app x 中,文字必须写在 text 组件里,不能写在 view 的文本区域。鸿蒙平台从 HarmonyOS 4.61 开始支持 text 组件。本文围绕鸿蒙平台的 text 组件用法,梳理属性、场景、适配规则和常见问题。一、为什么文字必须写在 text 里
在 Web 中,div 里直接写文字没有问题。但 uni-app x 的 view 组件不支持文本区域,文字需要用 text 包裹。编译器虽然会自动包裹一层 text,但自动生成的 text 无法单独设置样式。因为 uni-app x 样式不继承,所以直接写在 view 里的文字,会出现样式不可控的问题。
<!-- 错误:文字直接写在 view 里 -->
<view>这是一段文字</view>
<!-- 正确:文字用 text 包裹 -->
<text>这是一段文字</text>
<!-- 编译器会自动包裹,但无法控制内层 text 样式 -->
<view style='color: red;'>这是一段文字</view>
<!-- 实际编译后变成 -->
<view style='color: red;'>
<text>这是一段文字</text>
</view>
<!-- 正确做法:直接用 text 设置样式 -->
<text style='color: red;'>这是一段文字</text>
二、核心属性与点击态
text 组件的核心属性包括样式控制等。点击态方面,hover-class 只在蒸汽模式(Vapor)下生效,非蒸汽模式的 text 组件不支持 hover 相关功能。鸿蒙平台还支持 flatten 属性,用于拍平组件层级,减少渲染节点数量,提升性能。
三、实战场景
1. 基础文本
<template>
<text style='font-size: 16px; color: #333;'>这是一段普通文本</text>
</template>
2. 单行文本省略
<template>
<text style='font-size: 14px; white-space: nowrap; text-overflow: ellipsis; lines: 1;'>这是一段很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长的文本</text>
</template>
3. 多行文本省略
可以用 lines 或 max-lines 控制显示行数,超出显示省略号。
<template>
<text style='font-size: 14px; lines: 3; text-overflow: ellipsis;'>这是一段很长的文本,超过三行会显示省略号。</text>
</template>
<template>
<text :max-lines='3' style='font-size: 14px;'>这是一段很长的文本,超过三行会显示省略号。</text>
</template>
4. 文本可选
让用户长按选中复制:
<template>
<text selectable='true' style='font-size: 14px; color: #333;'>这段文本可以长按选中复制</text>
</template>
5. 嵌套文本
text 可以嵌套 text,实现同一段落内不同样式。但子 text 不继承父 text 样式,需要单独设置。
<template>
<text style='font-size: 16px; color: #333;'>
<text style='font-weight: bold; color: #2196F3;'>加粗蓝色</text>
<text>普通文本</text>
<text style='color: #F44336;'>红色文本</text>
</text>
</template>
6. 点击态效果
蒸汽模式下支持 hover-class:
<template>
<text hover-class='text-hover' hover-start-time='100' hover-stay-time='200' style='font-size: 16px; color: #2196F3; padding: 10px;'>点击我试试</text>
</template>
<style>
.text-hover {
opacity: 0.7;
background-color: #E3F2FD;
}
</style>
7. 连续空格处理
编译期处理时,静态文本中的连续空格会合并。运行期变量中的空格根据 white-space 处理。
<template>
<!-- 编译期处理:静态文本连续空格会合并 -->
<text>这 有 多个 空格</text>
<!-- 运行期处理:变量中的空格根据 white-space 处理 -->
<text style='white-space: pre;'>{{textWithSpaces}}</text>
</template>
<script setup lang='uts'>
const textWithSpaces = ref('这 有 多个 空格')
</script>
8. 实体字符
静态文本实体字符会在编译期解码。变量中的实体字符根据 decode 处理。注意蒸汽模式(Vapor)废弃了 decode 属性,运行期不再解析实体字符。
<template>
<text>5 < 10 & 3 > 1</text>
<text decode='true'>{{entityText}}</text>
</template>
<script setup lang='uts'>
const entityText = ref('5 < 10')
</script>
四、鸿蒙平台适配要点
- HarmonyOS 4.61 开始支持 text 组件。
- 鸿蒙平台文字必须写在 text 组件里,不能写在 view 的文本区域。
- 鸿蒙平台 text 的子 text 不继承父 text 样式,需要单独设置。
- 鸿蒙平台蒸汽模式(Vapor)white-space 默认值为 keep,即保留所有空白字符,连续空格不会合并。
- App 平台 white-space 默认值为 keep,Web 平台默认值为 pre-line。
- 鸿蒙平台支持 flatten 属性,用于减少渲染节点。
- 嵌套 text 中,子 text 设置的排版样式(position、display、width、height、margin、padding 等)以及部分 text 独有样式(text-align、lines、white-space、text-overflow)不生效。
- 在 uni-app x 中,text 里的 \n 默认会换行,这点与 Web 不同,Web 中 \n 默认会被忽略。
与鸿蒙原生 Text 组件对比,原生写法如下:
// 鸿蒙原生写法
Text('这是一段文本')
.fontSize(16)
.fontColor('#333')
.fontWeight(FontWeight.Bold)
.maxLines(3)
.textOverflow({ overflow: TextOverflow.Ellipsis })
uni-app x 的 text 组件与原生 Text 几乎一样,都是用 CSS 属性控制样式。
五、常见踩坑记录
坑一:文字不能直接写在 view 里。必须用 text 包裹。
坑二:子 text 不继承父 text 样式。嵌套时需单独设置。
坑三:view 的文本区域会被自动包裹,但无法控制内层 text 样式,建议手动包裹。
坑四:\n 默认会换行,跟 Web 不同。
坑五:连续空格默认会合并。需要保留时,用变量加 white-space: pre。
坑六:蒸汽模式废弃 space 和 decode 属性。推荐用 CSS white-space 处理空格。
坑七:嵌套 text 排版样式不生效。
六、完整示例片段
下面是一个综合页面片段,覆盖基础文本、省略、可选、嵌套、样式和连续空格。
<template>
<scroll-view style='flex: 1;'>
<view style='padding: 15px; background-color: white; margin-bottom: 10px;'>
<text style='font-size: 18px; font-weight: bold; margin-bottom: 15px;'>基础文本</text>
<text style='font-size: 16px; color: #333; margin-top: 10px;'>普通文本</text>
<text style='font-size: 16px; color: #2196F3; font-weight: bold; margin-top: 8px;'>加粗蓝色文本</text>
<text style='font-size: 16px; color: #F44336; font-style: italic; margin-top: 8px;'>斜体红色文本</text>
<text style='font-size: 16px; text-decoration: underline; margin-top: 8px;'>下划线文本</text>
<text style='font-size: 16px; text-decoration: line-through; margin-top: 8px;'>删除线文本</text>
</view>
<view style='padding: 15px; background-color: white; margin-bottom: 10px;'>
<text style='font-size: 18px; font-weight: bold; margin-bottom: 15px;'>文本省略</text>
<text style='font-size: 14px; lines: 1; text-overflow: ellipsis; white-space: nowrap; margin-top: 10px;'>单行省略:这是一段很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长的文本</text>
<text style='font-size: 14px; lines: 2; text-overflow: ellipsis; margin-top: 10px;'>多行省略:这是一段很长的文本,超过两行会显示省略号。</text>
</view>
<view style='padding: 15px; background-color: white; margin-bottom: 10px;'>
<text style='font-size: 18px; font-weight: bold; margin-bottom: 15px;'>可选文本</text>
<text selectable='true' style='font-size: 14px; color: #333; margin-top: 10px; background-color: #F5F5F5; padding: 10px; border-radius: 5px;'>长按这段文字可以选中复制,试试看</text>
</view>
<view style='padding: 15px; background-color: white; margin-bottom: 10px;'>
<text style='font-size: 18px; font-weight: bold; margin-bottom: 15px;'>嵌套文本</text>
<text style='font-size: 16px; margin-top: 10px;'>
<text style='color: #333;'>普通文本 </text>
<text style='color: #2196F3; font-weight: bold;'>加粗蓝色 </text>
<text style='color: #F44336;'>红色文本 </text>
<text style='color: #4CAF50; text-decoration: underline;'>绿色下划线</text>
</text>
</view>
<view style='padding: 15px; background-color: white; margin-bottom: 10px;'>
<text style='font-size: 18px; font-weight: bold; margin-bottom: 15px;'>文本样式</text>
<text style='font-size: 16px; letter-spacing: 5px; margin-top: 10px;'>字间距 5px</text>
<text style='font-size: 16px; line-height: 2; margin-top: 10px;'>行高 2 倍,这是一段文字用来展示行高效果</text>
<text style='font-size: 16px; text-align: center; margin-top: 10px;'>居中对齐</text>
<text style='font-size: 16px; text-align: right; margin-top: 10px;'>右对齐</text>
<text style='font-size: 16px; text-shadow: 2px 2px 4px rgba(0,0,0,0.3); margin-top: 10px;'>文字阴影</text>
</view>
<view style='padding: 15px; background-color: white; margin-bottom: 10px;'>
<text style='font-size: 18px; font-weight: bold; margin-bottom: 15px;'>连续空格</text>
<text style='font-size: 14px; white-space: pre; margin-top: 10px;'>这 有 多个 空格</text>
<text style='font-size: 14px; margin-top: 10px;'>正常显示:这 有 多个 空格</text>
</view>
</scroll-view>
</template>
总结:
在鸿蒙平台使用 uni-app x 的 text 组件,关键规则是:文字必须写在 text 组件里,样式设置在 text 上,不要直接写在 view 里;子 text 不继承父 text 样式;\n 默认换行;连续空格在编译期会合并;App 与鸿蒙蒸汽模式 white-space 默认值为 keep,Web 为 pre-line;蒸汽模式废弃 space 和 decode 属性;嵌套 text 的排版样式不生效。养成用 text 包裹文字的习惯,可以避免大量样式和适配问题。
Re: 鸿蒙 uni-app x text组件避坑:样式不继承与空格处理
这篇避坑总结很实用,尤其是“文字必须写在 text 里”和“样式不继承”这两点,从 Web 转过来确实容易踩。编译器虽然会自动包一层 text,但没法单独控样式,这个坑很隐蔽。单行、多行省略、selectable、嵌套 text 子级要单独设样式、连续空格和实体字符在编译期与运行期的差异,也都讲到了。想问下 flatten 一般是在长列表或复杂卡片里开启更合适吗?另外 hover-class 只在蒸汽模式下生效,那非蒸汽模式下想要点击态效果,一般要怎么处理比较合适?Re: 鸿蒙 uni-app x text组件避坑:样式不继承与空格处理
感谢楼主整理,这些点确实很实用。我从 Web 转过来也踩过在 view 里直接写文字的坑,当时样式怎么调都不对,还以为是优先级问题,后来才明白 uni-app x 样式不继承,编译器自动包的那层 text 根本没法单独控制。现在都老老实实把文字写在 text 里,需要不同样式就嵌套 text 并单独设置,虽然写起来啰嗦一点,但至少可控。 单行和多行省略那段也很有用,lines 和 max-lines 确实容易混。selectable 长按复制、连续空格在静态文本和运行期变量里处理方式不一样,这些细节平时很容易忽略。还有蒸汽模式下才支持 hover-class、废弃 decode 属性,这些也记下了。 实体字符那段好像还没贴完?如果后续能补上就更好。整体很干货,感谢分享。Re: 鸿蒙 uni-app x text组件避坑:样式不继承与空格处理
感谢分享,内容很实用。文字必须写在 text 里、不能依赖 view 的文本区域这点确实关键,自动包裹的 text 样式不可控也很容易踩。嵌套 text 不继承父样式、单行和多行省略、selectable、flatten、蒸汽模式下 hover-class 这些点总结得很清楚。连续空格在编译期和运行期处理不同,以及实体字符在静态文本和变量里的差异,也很容易忽略。实体字符那段好像没发完,尤其蒸汽模式废弃 decode 之后,变量里的实体字符怎么处理,如果后续能补上就更好了。
页:
[1]