uni-app x 的 CSS white-space 属性完全指南:空白字符处理、换行规则与跨端兼容
【免费下载链接】uni-appA cross-platform framework using Vue.js项目地址: https://gitcode.com/gh_mirrors/un/uni-app
本文以 docs/css/white-space.md 为核心,系统讲解 uni-app x 中
white-space属性的语法、全部属性值语义、默认值差异与平台兼容性,并结合仓库内的示例源码 src/pages/CSS/text/white-space.uvue、text 组件空白字符处理规则(docs/component/text.md)以及自动化测试用例,深度剖析其底层实现与 HBuilderX 5.0 的行为调整。读完本文,你将掌握:如何精确控制 App(Android/iOS/HarmonyOS)与 Web 端文本的空格合并、换行符保留、行末空白裁剪与自动换行行为,理解keep这一 uni-app x 特有的高性能属性值,并能在真实项目中正确使用white-space与space属性、flatten拍平模式的组合规则。
属性概述
white-space属性用于设置如何处理元素中的空白字符(空格、换行符、制表符)以及文本是否自动换行。
在 uni-app x 中,这一属性主要作用于 text 和 button 两个组件。由于 uni-app x 存在text组件(Web 没有的组件),且非 Web 平台(包括小程序平台)都不支持<br>换行,因此 uni-app x 专门设计了text组件中的\n默认不忽略、直接换行的行为——无论 App 平台默认值keep还是 Web 平台默认值pre-line,都保持这一表现。这也使得white-space在 uni-app x 中成为控制多行文本渲染的关键样式。
uni-app x 兼容性
| Web | Android | iOS | HarmonyOS | | :- | :- | :- | :- | | 4.0 | 4.0 | 4.11 | 4.61 |
上表为属性基础兼容性版本要求(对应 HBuilderX 相关版本)。
App 平台拍平(flatten)兼容性 @flatten_compatibility
| Android(Vapor) | iOS(Vapor) | HarmonyOS(Vapor) | | :- | :- | :- | | 5.21 | 5.11 | 5.0 |
该表反映 App 端 Vapor 引擎在拍平(flatten)渲染模式下的兼容版本。
语法与取值
语法
white-space: normal | pre | nowrap | pre-wrap | pre-line | break-spaces | [ <'white-space-collapse'> || <'text-wrap'> || <'white-space-trim'> ];- 值限制:
enum(枚举值),取值为下方属性值表中的名称,其中keep为 uni-app x 平台扩展值(不属于 W3C 标准枚举)。
white-space 的属性值
| 名称 | 兼容性 | 描述 | | :- | :- | :- | | normal | Web: 4.0; Android: 4.0; iOS: 4.11; HarmonyOS: 4.61 | 换行符(\n)当做空白符处理,连续的多个空白字符会合并为一个空格,文本遇到边界会自动换行,行末空白字符移除。 | | nowrap | Web: 4.0; Android: 4.0; iOS: 4.11; HarmonyOS: 4.61 | 换行符(\n)当做空白符处理,连续的多个空白字符会合并为一个空格,文本遇到边界不会自动换行,行末空白字符移除。 | | pre | Web: 4.0; Android: 4.81; iOS: 4.81; HarmonyOS(VDOM): x; HarmonyOS(Vapor): 5.0 | 换行符(\n)保留并换行显示,连续的多个空白字符保留,文本遇到边界不会自动换行,行末空白字符保留。 | | pre-wrap | Web: 4.0; Android: 4.81; iOS: 4.81; HarmonyOS(VDOM): x; HarmonyOS(Vapor): 5.0 | 换行符(\n)保留并换行显示,连续的多个空白字符保留,文本遇到边界会自动换行,行末空白字符保留但"不占位置"。 | | pre-line | Web: 4.0; Android: 4.81; iOS: 4.81; HarmonyOS(VDOM): x; HarmonyOS(Vapor): 5.0 | 换行符(\n)保留并换行显示,连续的多个空白字符会合并为一个空格,文本遇到边界会自动换行,行末空白字符移除。 | | break-spaces | Web: 4.0; Android: 4.81; iOS: 4.81; HarmonyOS(VDOM): x; HarmonyOS(Vapor): 5.0 | 换行符(\n)保留并换行显示,连续的多个空白字符保留,文本遇到边界会自动换行,行末空白字符换行处理。 | | keep | Web: x; Android: 5.0; iOS: 5.0; HarmonyOS(VDOM): x; HarmonyOS(Vapor): 5.0 | 不对空白字符处理,保持原始值。换行符(\n)保留并换行显示,连续的多个空白字符保留,文本遇到边界会自动换行,行末空白字符保留。 |
七个取值可从三个维度快速记忆:
- 换行符
\n是否保留:normal/nowrap将\n当作普通空白符(合并),其余取值均保留并换行显示; - 连续空白字符是否合并:
normal/nowrap/pre-line合并为单个空格,pre/pre-wrap/break-spaces/keep全部保留; - 边界处是否自动换行:仅
nowrap与pre不自动换行,其余均自动换行。
默认值 @default-value
| 平台 | 默认值 | | :- | :- | | uvue-app | keep | | uvue-web | pre-line |
注意:W3C 规范默认值为normal。uni-app x 之所以在 App 端默认采用keep,是为了避免对连续空白字符做合并处理,从而提升 text 组件的渲染性能(详见下文"HBuilderX 5.0 版本调整")。
适用组件 @unix-tags
- text
- button
空白字符处理不止由 white-space 决定
编译期:模板静态文本先行处理
对于写在模板中的 text 组件里的空白字符,在编译阶段会由编译器先行处理。以 docs/component/text.md 中的示例为准:
<template> <text id="t1"> a bc def g hi </text> </template>编译期间会将 template 中静态文本的所有空白字符转换为空格,并将多个连续空格合并为一个空格,首尾空格保留。如上示例编译后 text 组件中的文本内容为" a bc def g hi "。
注意:编译期间不会处理变量中的空白字符。变量文本交由各平台运行环境根据white-space样式处理并渲染,例如:
<template> <text>{{text}}</text> </template> <script lang="uts" setup> let text = ' a bc def\tg\nhi ' </script>上面代码中的
\t和\n是转义字符:\t表示制表符(Tab),\n表示换行符(Line Feed)。
运行期:space 属性与 white-space 样式共同决定
运行期的空白字符处理由space属性与white-space样式共同决定:
space属性:仅处理空格字符;white-space样式:处理所有空白字符(空格、换行符、制表符)。
如果 text 组件配置了space属性值,会先根据space属性值处理文本中的空格,再根据white-space样式处理。蒸汽模式(Vapor)已废弃space属性,推荐统一改用 CSSwhite-space来处理空白字符。
各平台存在如下差异:
- App-Android 平台:配置了
space属性后将只处理空格转换,忽略white-space样式值,即按white-space: keep处理; - App-iOS 平台:配置了
space属性后将先处理空格转换,再根据white-space属性值处理空白字符; - 后续版本将统一废弃
space属性,推荐统一改用 CSSwhite-space。
与 text-overflow 的组合使用
white-space: nowrap常与text-overflow配合实现单行省略号效果。仓库示例 src/pages/CSS/text/text-overflow.uvue 中大量使用这一组合,如:
<text class="font-size-20" style="text-overflow: ellipsis;white-space: nowrap;">{{data.singleLineText}}</text> <text class="font-size-20" style="text-overflow: ellipsis;white-space: nowrap;width: 100px;">{{data.multiLineText}}</text>当需要实现"任意宽度单行截断 + 省略号"时,white-space: nowrap是必不可少的前提——它保证文本不换行,配合width与text-overflow: ellipsis完成截断显示。
HBuilderX 5.0 版本调整
app 平台、web 平台在 HBuilderX 5.0 版本调整了white-space属性的实现:之前接近小程序的表现,之后按 W3C 标准规范执行。同时为了 text 组件性能考虑,app 平台新增支持keep属性值,且默认为keep。
默认值调整
- app-android、app-ios 平台:新增支持取值
keep,默认值由normal调整为keep; - app-harmony 平台蒸汽模式(Vapor):支持取值
keep,默认值为keep; - web 平台:默认值由
normal调整为pre-line。
调整前实现规范(旧行为对照)
调整前的实现与小程序表现接近,各取值行为如下(注意与上表新规范的差异):
- normal(与调整后的 pre-line 效果一致):换行符(\n)保留并换行显示,连续的多个空白字符会合并为一个空格,文本遇到边界会自动换行,行末空白字符移除;
- nowrap:换行符(\n)保留并换行显示,连续的多个空白字符会合并为一个空格,文本遇到边界不会自动换行,行末空白字符移除;
- pre:换行符(\n)保留并换行显示,连续的多个空白字符保留,文本遇到边界不会自动换行,行末空白字符保留;
- pre-wrap:换行符(\n)保留并换行显示,连续的多个空白字符保留,文本遇到边界会自动换行,行末空白字符保留;
- pre-line:换行符(\n)保留并换行显示,连续的多个空白字符会合并为一个空格,文本遇到边界会自动换行,行末空白字符移除;
- break-spaces:换行符(\n)保留并换行显示,连续的多个空白字符保留,文本遇到边界会自动换行,行末空白字符保留。
关键差异点:调整前normal与nowrap会保留\n换行(接近小程序表现);调整后按 W3C 规范,normal与nowrap将\n当作普通空白符处理(合并为一个空格)。若你的旧项目依赖normal保留换行,升级到 HBuilderX 5.0 后需改用pre-line或keep以获得一致效果。
各平台当前实现要点
- App-Android、App-iOS:自 HBuilderX 5.0 起,
white-space控制空白字符处理逻辑与 W3C 规范一致,默认值为keep。如示例' a bc def\tg\nhi '将保留所有空格(连续空格不会合并)、制表符、换行符进行渲染,a 和 b 之间有 3 个空格; - App-Harmony:蒸汽模式(Vapor)下
white-space控制空白字符处理逻辑与 W3C 规范一致,默认值为keep; - Web:自 HBuilderX 5.0 起逻辑与 W3C 规范一致,默认值为
pre-line。同一示例将合并空格(连续空格合并为 1 个空格),制表符转换为空格,保留换行符进行渲染,a 和 b 之间只有 1 个空格。
Web 与 App 的本质差异:Web 默认值pre-line虽然支持\n换行,同时会把\n以外的多个连续空白字符合并为 1 个;App 为了提升性能,默认值为keep,即默认不会合并连续的空白字符。
实战示例:动态切换 white-space
仓库内置了完整的演示页面 src/pages/CSS/text/white-space.uvue,同时演示普通渲染与拍平(flatten)渲染下 7 个枚举值(含空字符串)与自定义值的设置/获取,可直接在 hello uni-app x 中运行查看效果。核心逻辑如下:
<template> <scroll-view style="padding: 10px 0px; background-color: gray;justify-content: center;" direction="horizontal"> <!-- 普通版本 --> <text class="text" :style="{ whiteSpace: data.whiteSpace }">{{data.multiLineText}}</text> </scroll-view> <text>拍平</text> <scroll-view style="padding: 10px 0px; background-color: gray;justify-content: center;" direction="horizontal"> <!-- 拍平版本 --> <text class="text" :style="{ whiteSpace: data.whiteSpace }" flatten>{{data.multiLineText}}</text> </scroll-view> </template>关键点说明:
- 枚举数据:脚本中定义了完整的枚举列表,其中包含空字符串
''(空值情况)与keep:
const whiteSpaceEnum: ItemType[] = [ { value: 0, name: '' }, { value: 1, name: 'normal' }, { value: 2, name: 'nowrap' }, { value: 3, name: 'pre' }, { value: 4, name: 'pre-wrap' }, { value: 5, name: 'pre-line' }, { value: 6, name: 'break-spaces' }, { value: 7, name: 'keep' } ]- 多行测试文本:文本同时包含 Tab 缩进、换行符与单行长段落,便于肉眼对比各取值差异:
const data = reactive({ multiLineText: `HBuilderX, 轻巧、 极速, 极客编辑器; uni-app x, 终极跨平台方案; uts, 大一统语言 HBuilderX,轻巧、极速,极客编辑器;uni-app x,终极跨平台方案;uts,大一统语言`, whiteSpace: 'normal', whiteSpaceActual: '', whiteSpaceActualFlat: '' })- setProperty 设置与 getPropertyValue 获取:通过
UniTextElement类型引用 text 节点,动态设置并读取样式值,配合nextTick确保样式应用后再取值:
const textRef = ref(null as UniTextElement | null) const textRefFlat = ref(null as UniTextElement | null) const getPropertyValues = () => { data.whiteSpaceActual = textRef.value?.style.getPropertyValue('white-space') ?? '' data.whiteSpaceActualFlat = textRefFlat.value?.style.getPropertyValue('white-space') ?? '' } const changeWhiteSpace = (value: string) => { data.whiteSpace = value textRef.value?.style.setProperty('white-space', value) textRefFlat.value?.style.setProperty('white-space', value) // 使用 nextTick 确保样式已应用后再获取值 nextTick(() => { getPropertyValues() }) }- 样式细节:示例中
.text设置了font-size: 16px; align-self: flex-start;,注释明确说明"需要设置 align-self,text 组件才会自适应宽度";direction="horizontal"的横向 scroll-view 便于观察不换行文本的溢出效果。
拍平(flatten)模式
示例中普通版本与拍平版本(带flatten属性)各渲染一份文本,可对比两种渲染模式下的空白处理一致性。flatten是 App 端的一种渲染优化(拍平),将组件样式合并为原生层绘制。从拍平兼容性表可见,Vapor 引擎下 Android 5.21 / iOS 5.11 / HarmonyOS 5.0 起支持。在实际开发中,若同时使用white-space与flatten,建议在真机上对两种渲染模式分别验证显示效果。
自动化测试验证
仓库的自动化测试 src/pages/CSS/set-css.test.js(约第 792-802 行)覆盖了该示例页面的行为断言:
{ path: '/pages/CSS/text/white-space', method: 'radioChangeWhiteSpace', valueIndex: 3, styleName: 'white-space', expectedValue: { whiteSpace: 'pre', whiteSpaceActual: 'pre', whiteSpaceActualFlat: 'pre', } }该用例通过radioChangeWhiteSpace方法选择第 3 个枚举值(pre),并断言设置值whiteSpace、普通渲染实际值whiteSpaceActual、拍平渲染实际值whiteSpaceActualFlat三者均为pre,从侧面印证了:通过setProperty('white-space', value)设置后,getPropertyValue('white-space')可以原样读回,且普通模式与拍平模式下行为一致。
注意事项与最佳实践
- 性能优先选 keep:App 端默认
keep意味着不做空白合并处理,渲染性能最优。若业务不需要折叠连续空格,保持默认即可; - 跨端一致性:需要"换行符保留 + 连续空格保留 + 自动换行"时,App 用
pre-wrap(或默认keep),Web 用pre-wrap;需要"换行符保留 + 空格折叠 + 自动换行"时,统一使用pre-line(Web 默认值即为此);需要单行不换行时统一使用nowrap; - 避免依赖 space 属性:蒸汽模式(Vapor)已废弃
space属性,且 Android 平台配置space后会忽略white-space样式(按keep处理),后续版本将统一废弃,应统一改用 CSSwhite-space; - 模板静态文本 vs 变量文本:模板中静态文本的空白字符在编译期已被合并处理,
white-space主要作用于变量文本的运行期渲染;若需要精确控制静态文本的空白,请通过变量传入文本内容; - \n 换行设计:uni-app x 非 Web 平台不支持
<br>换行,text 组件中的\n默认换行是框架设计行为,各取值下均不会被当作普通空格忽略(仅normal/nowrap按 W3C 新规范合并); - 升级注意:从旧版本(HBuilderX 5.0 之前)升级时,
normal/nowrap对\n的处理从"保留换行"变为"按空格合并",旧项目需评估文本渲染差异; - 与 text-overflow 联动:单行省略号(
text-overflow: ellipsis)必须搭配white-space: nowrap使用,参见 src/pages/CSS/text/text-overflow.uvue。
参见
- text 组件空白字符处理详解(含
space属性与各平台差异说明) - text-overflow 属性示例
- white-space 演示页面源码
- white-space 自动化测试用例
- button 组件文档
【免费下载链接】uni-appA cross-platform framework using Vue.js项目地址: https://gitcode.com/gh_mirrors/un/uni-app
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考