简体中文
组件类型:UniTextElement
文本
| Web | 微信小程序 | Android | iOS | HarmonyOS | HarmonyOS(Vapor) |
|---|---|---|---|---|---|
| 4.0 | 4.41 | 3.9 | 4.11 | 4.61 | 5.0 |
在app-uvue和app-nvue中,文本只能写在text中,而不能写在view的text区域。文本样式的控制也应该在text组件上写style,而不是在view的样式里写。
虽然app-uvue中写在view的text区域的文字,也会被编译器自动包裹一层text组件,看起来也可以使用。但这样会造成无法修改该text文字的样式,详见uvue的样式不继承章节。
| 名称 | 类型 | 默认值 | 兼容性 | 描述 | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| selectable | boolean | false | 文本是否可选 | |||||||||||||
| space | string | - | 显示连续空格,App平台蒸汽模式(Vapor)将废弃此属性 | |||||||||||||
| ||||||||||||||||
| decode | boolean | false | 是否解码,App平台蒸汽模式(Vapor)将废弃此属性 | |||||||||||||
| user-select | boolean | - | (boolean) 文本是否可选,该属性会使文本节点显示为 inline-block | |||||||||||||
| hover-class | string(string.ClassString) | "none" | 指定按下去的样式类。当 hover-class="none" 时,没有点击态效果 | |||||||||||||
| hover-stop-propagation | boolean | false | 指定是否阻止本节点的祖先节点出现点击态(祖先节点:指根节点到该节点路径上的所有节点都是这个节点的祖先节点) | |||||||||||||
| hover-start-time | number | 50 | 按住后多久出现点击态,单位毫秒 | |||||||||||||
| hover-stay-time | number | 400 | 手指松开后点击态保留时间,单位毫秒 | |||||||||||||
| max-lines | number | - | 文本的最大行数,默认不限制最大行数 | |||||||||||||
| flatten | boolean | false | 是否拍平组件 | |||||||||||||
App平台蒸汽模式(Vapor) text 组件新增支持 hover-class 实现点击态效果。
注意
text 组件不支持 hover 相关功能text 组件不支持 hover 相关功能空白字符并不只是指空格键敲出来的那个空格字符,它是一个字符集合。
包括以下字符:
空白字符的处理分为 编译期处理 和 运行期处理 两个阶段。
编译期间仅处理template中直接写在text节点中的静态文本,如下示例1:
<template>
<text id="t1"> a bc def g
hi </text>
</template>
编译期间会将template中静态文本的所有空白字符转换为空格,并将多个连续空格合并为一个空格,首尾空格保留。
如上示例1编译后text组件中的文本内容为“ a bc def g hi ”。
注意:编译期间不会处理变量中的空白字符。
由 space 属性 和 white-space 样式共同决定。
space 属性:仅处理空格字符如下示例2,演示text组件使用变量中的文本:
<template>
<text>{{text}}</text>
</template>
<script lang="uts" setup>
let text = ' a bc def\tg\nhi '
</script>
上面代码中的 \t 和 \n 是
转义字符,\t 表示 制表符 (Tab),\n 表示 换行符 (Line Feed)
编译期间不会对变量中的空白字符做处理,而是由各平台运行环境根据 white-space 样式处理并渲染。
space属性
如果text组件配置了space属性值,会先根据space属性值处理文本中的空格,再根据 white-space 样式处理。
蒸汽模式(Vapor)废弃了space属性。推荐统一改用css white-space来处理空白字符。
App-Android、App-iOS平台
HBuilderX5.0版本开始 app-andorid/app-ios平台调整 white-space 样式控制空白字符处理逻辑与 W3C 规范一致,
默认值为 keep。
如上示例2中将保留所有空格(连续空格不会合并)、制表符、换行符进行渲染,a和b之间有3个空格。
app-andorid/app-ios平台避免使用 space 属性处理空格,存在以下平台差异:
space 属性将只处理空格转换,忽略 white-space 样式值,即按 white-space: keep 处理。space 属性将先处理空格转换,再根据 white-space 属性值处理空白字符。
后续统一会废弃 space 属性,推荐统一改用css white-space 来处理空白字符。App-Harmony平台
蒸汽模式(Vapor) white-space 样式控制空白字符处理逻辑与 W3C 规范一致,默认值为 keep。
Web平台
HBuilderX5.0版本开始 web平台调整 white-space 样式控制空白字符处理逻辑与 W3C 规范一致,
默认值为 pre-line。
如上示例2中将合并空格(连续空格合并为1个空格),制表符转换为空格,保留换行符进行渲染,a和b之间只有1个空格。
uni-app x中有text组件,这是一个web没有的组件。且uni-app x在非web平台,包括小程序平台,都不支持
换行,所以uni-app x设计为text组件中的\n默认不会忽略,而是换行。
不管app平台默认值keep,还是web平台默认值pre-line,都是这个表现。
web的默认值preline,虽然支持\n换行,同时会合并\n以外的其他多个连续空白字符为1个。这是web与app的不同。app为了提升性能,默认值为keep,即默认不会合并连续的空白字符。
实体字符(Entity Character)是在标记语言(如 vue/uvue 的 template 中)或编程中,用来表示那些具有特殊含义、无法直接输入或显示的字符的一种编码方式。
实体字符通常由三部分组成,以 &开头,以 ;结尾,中间是实体名称或编号。
常见的实体字符包括:
实体字符的处理分为 编译期处理 和 运行期处理 两个阶段。
某些字符在标记语言中是预留的。例如,template会将 < 视作标签的开始。如果想在文本上显示“5 < 10”,直接输入 < 可能会导致编译器误以为后面跟着一个标签,从而引起编译报错,这时需要使用实体字符 < 表示 <,如下示例:
<template>
<text id="t1">5 < 10</text>
</template>
编译期间会将template中静态文本的所有实体字符解析为真实字符。
如上示例编译后text组件中的文本内容为“5 < 10”。
注意:编译期间不会处理变量中的实体字符。
由 decode 属性值决定是否在运行期解析实体字符,默认运行期不解析实体字符。
如下示例,演示text组件使用变量中的文本,:
<template>
<text decode="false">{{text}}</text>
</template>
<script lang="uts" setup>
let text = '5 < 10'
</script>
编译期间不会对变量中的实体字符做转换,而是由各平台运行环境根据 decode 属性值决定是否转换。
decode 属性值设置为 true 时:运行期转换实体字符,上面示例字符串显示为 “5 < 10”decode 属性值设置为 false 时:运行期不转换实体字符,上面示例字符串显示为 “5 < 10”注意
蒸汽模式(Vapor)将废弃 decode 属性,运行期不再解析实体字符。
| 子组件 | 兼容性 |
|---|---|
| text |
text组件在web浏览器渲染(含浏览器、小程序webview渲染模式、app-vue)和uvue中,可以并只能嵌套text组件。
app平台 text 组件虽然支持嵌套,但注意限制:
<text></text>标签之间,例如:<text><text>嵌套文本1</text><text>嵌套文本2</text></text>,避免出现预期外的效果。HBuilderX4.51版本起 text组件嵌套时,子组件支持点击事件响应。之前版本如有这方面需求,请改用 rich-text
示例为hello uni-app x alpha分支,与最新HBuilderX Alpha版同步。与最新正式版同步的master分支示例另见
示例
<template>
<!-- #ifdef APP -->
<scroll-view style="flex: 1">
<!-- #endif -->
<page-head :title="title"></page-head>
<view class="uni-padding-wrap uni-common-mt">
<!-- 单行文本测试 -->
<text class="uni-title-text">单行文本</text>
<view class="text-box">
<text class="styled-text single-line">{{ singleLineText }}</text>
</view>
<text class="uni-subtitle-text">单行文本 - 拍平</text>
<view class="text-box" flatten>
<text class="styled-text single-line" flatten>{{ singleLineText }}</text>
</view>
<!-- 多行文本测试 -->
<text class="uni-title-text">多行文本</text>
<view class="text-box">
<text class="styled-text">{{ multiLineText }}</text>
</view>
<text class="uni-subtitle-text">多行文本 - 拍平</text>
<view class="text-box" flatten>
<text class="styled-text" flatten>{{ multiLineText }}</text>
</view>
<text class="uni-title-text">嵌套的text样式合集</text>
<text class="uni-common-mt uni-common-mb">
<text class="styled-text">text嵌套text的内容:</text>
<text class="styled-text">{{multiLineText}}</text>
</text>
<!-- 自定义组件拍平 -->
<text class="uni-title-text">自定义组件:右边拍平</text>
<view class="view-row">
<child></child>
<child flatten></child>
</view>
<!-- 动态文本测试 -->
<text class="uni-title-text">动态文本</text>
<view class="dynamic-text-box">
<text class="text">{{ text }}</text>
</view>
<text class="uni-subtitle-text">动态文本 - 拍平</text>
<view class="dynamic-text-box" flatten>
<text class="text" flatten>{{ text }}</text>
</view>
<view class="uni-btn-v">
<button class="uni-btn" type="primary" :disabled="!canAdd" @click="add">
add line
</button>
<button class="uni-btn" type="warn" :disabled="!canRemove" @click="remove">
remove line
</button>
<button class="uni-btn" type="primary" @click="textProps">
更多属性示例
</button>
<button class="uni-btn" type="primary" @click="textWriter">
打字机效果示例
</button>
<!-- #ifdef APP-ANDROID -->
<button class="uni-btn" type="primary" @click="textLayout">
文本测量
</button>
<!-- #endif -->
</view>
<!-- #ifdef VUE3-VAPOR -->
<navigator url="/pages/template/4050/4050">
<button class="uni-btn uni-common-mb">组件性能测试</button>
</navigator>
<!-- #endif -->
</view>
<!-- #ifdef APP -->
</scroll-view>
<!-- #endif -->
</template>
<script setup lang="uts">
import Child from './child.uvue'
const title = ref('text')
// 单行文本
const singleLineText = ref('单行文本:16px字体、500粗细、斜体、下划线、1px字间距、1.8行高、文本阴影、居中对齐、不换行溢出省略、带边框圆角、内外边距、背景色')
// 多行文本
const multiLineText = ref('多行文本:字体(16px/500粗细/斜体)、装饰(下划线/阴影)、间距(1px字间距/1.8行高)、对齐(左对齐)、盒模型(边框/圆角/内外边距/背景色)。\n 第二行:展示自动换行效果及所有CSS样式的渲染表现。')
// 动态文本测试数据
const texts: string[] = [
'HBuilderX,轻巧、极速,极客编辑器',
'uni-app x,终极跨平台方案',
'uniCloud,js serverless云服务',
'uts,大一统语言',
'uniMPSdk,让你的App具备小程序能力',
'uni-admin,开源、现成的全端管理后台',
'uni-id,开源、全端的账户中心',
'uni-pay,开源、云端一体、全平台的支付',
'uni-ai,聚合ai能力',
'uni-cms,开源、云端一体、全平台的内容管理平台',
'uni-im,开源、云端一体、全平台的im即时消息',
'uni统计,开源、完善、全平台的统计报表',
'......'
]
const text = ref('')
const canAdd = ref(true)
const canRemove = ref(false)
let extraLine: string[] = []
const add = () => {
extraLine.push(texts[extraLine.length % 12])
text.value = extraLine.join('\n')
canAdd.value = extraLine.length < 12
canRemove.value = extraLine.length > 0
}
const remove = () => {
if (extraLine.length > 0) {
extraLine.pop()
text.value = extraLine.join('\n')
canAdd.value = extraLine.length < 12
canRemove.value = extraLine.length > 0
}
}
const textProps = () => {
uni.navigateTo({
url: '/pages/component/text/text-props'
})
}
const textWriter = () => {
uni.navigateTo({
url: '/pages/component/text/text-writer'
})
}
const textLayout = () => {
uni.navigateTo({
url: '/pages/component/text/text-layout'
})
}
</script>
<style>
.view-row {
flex-direction: row;
background: #fff;
justify-content: space-around;
}
.text-box {
margin-bottom: 15px;
padding: 10px;
display: flex;
min-height: 60px;
background-color: #ffffff;
justify-content: center;
align-items: center;
}
/* 包含所有文字和排版CSS的综合样式 */
.styled-text {
/* 文字专用CSS */
/* 字体相关 */
font-size: 16px;
font-weight: 500;
font-style: italic;
color: #1a1a1a;
/* 行高与字间距 */
line-height: 1.8;
letter-spacing: 1px;
/* 对齐 */
text-align: left;
/* 文字装饰 */
text-decoration-line: underline;
/* 文本阴影 */
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.3);
/* 排版CSS */
width: 100%;
margin: 5px 0;
padding: 8px 12px;
border: 1px solid #e0e0e0;
border-radius: 4px;
background-color: #f9f9f9;
}
/* 单行文本特定样式 */
.single-line {
white-space: nowrap;
text-overflow: ellipsis;
text-align: center;
}
.dynamic-text-box {
margin-bottom: 15px;
padding: 10px;
display: flex;
min-height: 50px;
background-color: #ffffff;
border: 1px solid #dddddd;
border-radius: 5px;
justify-content: center;
align-items: center;
}
.text {
font-size: 14px;
color: #353535;
line-height: 22px;
text-align: center;
}
</style>
注意
App 端不支持 text 组件中渲染多段文本,如果 text 组件中的文本是动态的,可以将计算后的结果通过数据给到 text 组件, 而不是在模板中通过 template 拼接多段文本, 以免出现渲染异常,例如:
<template>
<view>
<text>
<template v-for="item in list">
<template v-if="item['show']">{{item['text']}}</template>
</template>
</text>
</view>
</template>
<script setup lang="uts">
const list = ref([
{
show: true,
text: 'a'
},{
show: false,
text: 'b'
},{
show: true,
text: 'c'
}
])
</script>
上述代码应调整为:
<template>
<view>
<text>{{textValue}}</text>
</view>
</template>
<script setup lang="uts">
const list = ref([
{
show: true,
text: 'a'
}, {
show: false,
text: 'b'
}, {
show: true,
text: 'c'
}
])
const textValue = computed((): string => {
let res = ''
list.value.forEach(item => {
if (item['show'] === true) {
res += item['text']
}
})
return res
})
</script>