PreviewText
阅读态组件,主要用来实现 Input、Picker、DatePicker 这类表单组件的只读展示。
PreviewText 是无渲染配置组件。日常使用时不需要手动替换组件,只要字段或表单进入 readPretty,已经接入 mapReadPretty 的 Vant 表单组件会自动切换到对应的 PreviewText.* 展示组件。
阅读态
下面的示例把整个 Form 设置为 readPretty,集中展示当前 Vant 包中已经实现阅读态映射的组件。点击底部按钮可以像 Element Plus 封装库示例一样,通过 form.setState 在编辑态和阅读态之间切换。
提示
Upload 组件的编辑态的文件预览来自 dataSource/fileList,如果需要编辑态回显,除了字段值本身,还需要同时准备 dataSource/fileList
vue
<script setup lang="ts">
import type { UploadPreviewFile } from '@silver-formily/vant'
import { createForm } from '@silver-formily/core'
import {
Area,
Calendar,
Cascader,
Checkbox,
DatePicker,
Form,
FormButtonGroup,
FormItem,
Input,
Picker,
PickerGroup,
Radio,
Rate,
Signature,
Slider,
Stepper,
Switch,
TimePicker,
Upload,
} from '@silver-formily/vant'
import { Field } from '@silver-formily/vue'
import { areaList } from '@vant/area-data'
import { Button as VanButton } from 'vant'
import { ref } from 'vue'
import { cityOptions as cascaderOptions } from '../cascader/shared'
import { appointmentOptions } from '../picker-group/shared'
import { cityOptions, regionColumns } from '../picker/shared'
const signatureValue = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(`
<svg xmlns="http://www.w3.org/2000/svg" width="240" height="96" viewBox="0 0 240 96">
<path d="M24 58 C58 30, 62 82, 96 48 S152 54, 184 36 S206 44, 216 32" fill="none" stroke="#1989fa" stroke-width="5" stroke-linecap="round" />
</svg>
`)}`
function openExternalFile(url: string) {
window.open(url, '_blank', 'noopener')
}
function isImageFile(file: { file?: File, isImage?: boolean, url?: string }) {
if (file.isImage) {
return true
}
if (file.file?.type?.startsWith('image/')) {
return true
}
return /\.(?:bmp|gif|jpe?g|png|svg|webp)$/i.test(file.url ?? '')
}
const previewFile: UploadPreviewFile = (file) => {
if (isImageFile(file)) {
return
}
if (file.url) {
openExternalFile(file.url)
}
}
const attachmentFiles = [
{
name: '门店照片.jpg',
url: 'https://fastly.jsdelivr.net/npm/@vant/assets/cat.jpeg',
},
{
name: '巡检记录.pdf',
url: 'https://mozilla.github.io/pdf.js/web/compressed.tracemonkey-pldi-09.pdf',
},
]
const form = createForm({
readPretty: true,
values: {
username: 'Silver Formily',
deliveryType: 'express',
features: ['photo', 'location'],
enabled: true,
quantity: 6,
score: 4,
progress: 68,
signature: signatureValue,
attachments: attachmentFiles,
cascader: ['330000', '330100', '330106'],
areaCode: '330102',
picker: 'hz',
pickerPath: ['zj', 'hz'],
pickerGroup: ['hz', 'pm'],
date: '2026-03-23',
time: '14:30',
rangeDate: ['2026-03-24', '2026-03-28'],
},
})
const isReadPretty = ref(true)
function toggleReadPretty() {
isReadPretty.value = !isReadPretty.value
form.setState((state) => {
state.editable = !isReadPretty.value
})
}
</script>
<template>
<Form :form="form">
<Field
name="username"
title="文本"
:decorator="[FormItem]"
:component="[Input]"
/>
<Field
name="deliveryType"
title="单选"
:decorator="[FormItem]"
:component="[Radio.Group]"
:data-source="[
{ label: '快递寄送', value: 'express' },
{ label: '门店自提', value: 'pickup' },
{ label: '同城闪送', value: 'instant' },
]"
/>
<Field
name="features"
title="多选"
:decorator="[FormItem]"
:component="[Checkbox.Group]"
:data-source="[
{ label: '拍照', value: 'photo' },
{ label: '定位', value: 'location' },
{ label: '扫码', value: 'scan' },
]"
/>
<Field
name="enabled"
title="开关"
:decorator="[FormItem]"
:component="[Switch]"
/>
<Field
name="quantity"
title="步进器"
:decorator="[FormItem]"
:component="[Stepper]"
/>
<Field
name="score"
title="评分"
:decorator="[FormItem]"
:component="[Rate]"
/>
<Field
name="progress"
title="进度"
:decorator="[FormItem]"
:component="[Slider]"
/>
<Field
name="signature"
title="签名"
:decorator="[FormItem, { labelAlign: 'top' }]"
:component="[Signature]"
/>
<Field
name="attachments"
title="附件"
:decorator="[FormItem, { labelAlign: 'top' }]"
:component="[Upload, { previewFile }]"
:data-source="attachmentFiles"
/>
<Field
name="cascader"
title="级联"
:decorator="[FormItem, { isLink: true }]"
:component="[Cascader]"
:data-source="cascaderOptions"
/>
<Field
name="areaCode"
title="省市区"
:decorator="[FormItem, { isLink: true }]"
:component="[Area, { areaList }]"
/>
<Field
name="picker"
title="选择器"
:decorator="[FormItem, { isLink: true }]"
:component="[Picker]"
:data-source="cityOptions"
/>
<Field
name="pickerGroup"
title="分步选择"
:decorator="[FormItem, { isLink: true }]"
:component="[PickerGroup]"
:data-source="appointmentOptions"
/>
<Field
name="date"
title="日期"
:decorator="[FormItem, { isLink: true }]"
:component="[DatePicker]"
/>
<Field
name="time"
title="时间"
:decorator="[FormItem, { isLink: true }]"
:component="[TimePicker]"
/>
<Field
name="rangeDate"
title="日历区间"
:decorator="[FormItem, { isLink: true }]"
:component="[Calendar, {
type: 'range',
minDate: '2026-03-01',
maxDate: '2026-04-30',
}]"
/>
<Field
name="cascader"
title="格式化"
:decorator="[FormItem, { isLink: true }]"
:component="[Cascader, {
options: cascaderOptions,
displayFormatter: (_value, selectedOptions) => selectedOptions.map(option => option?.text).filter(Boolean).join(' -> '),
}]"
/>
<Field
name="pickerPath"
title="直接列数据"
:decorator="[FormItem, { isLink: true }]"
:component="[Picker, {
columns: regionColumns,
displayFormatter: (_value, selectedOptions) => selectedOptions.map(option => option?.text || option?.label).filter(Boolean).join(' / '),
}]"
/>
<FormButtonGroup>
<VanButton
type="primary"
block
@click="toggleReadPretty"
>
{{ isReadPretty ? '切换到编辑态' : '切换到阅读态' }}
</VanButton>
</FormButtonGroup>
</Form>
</template>组件映射
| 表单组件 | 阅读态组件 | 说明 |
|---|---|---|
Input / Input.TextArea / Stepper | PreviewText.Input | 以文本方式展示字段值,支持 formatter |
Radio.Group / Checkbox.Group | PreviewText.Select | 根据 dataSource 展示选项文案 |
Switch | PreviewText.Switch | 以只读开关展示当前开关值 |
Rate | PreviewText.Rate | 以只读评分展示当前分值 |
Slider | PreviewText.Slider | 以只读滑块展示当前进度或区间 |
Signature | PreviewText.Signature | 回显已有签名图片 |
Upload | PreviewText.Upload | 复用 Vant Uploader 预览样式展示文件 |
Cascader | PreviewText.Cascader | 根据路径值和选项展示完整路径文案 |
Area / AreaPanel | PreviewText.Area | 根据省市区编码展示区域文案 |
Picker / PickerPanel | PreviewText.Picker | 支持单列、多列和级联选择结果 |
PickerGroup / PickerGroupPanel | PreviewText.PickerGroup | 展示分步选择后的组合结果 |
DatePicker / DatePickerPanel | PreviewText.DatePicker | 根据日期选择配置格式化展示 |
TimePicker / TimePickerPanel | PreviewText.TimePicker | 根据时间选择配置格式化展示 |
Calendar | PreviewText.Calendar | 支持单选、多选和区间日期展示 |
自定义占位符
可以用 PreviewText 包裹一组字段统一配置空值占位符。
vue
<PreviewText placeholder="暂无数据">
<Field name="name" read-pretty :component="[Input]" />
</PreviewText>API
PreviewText
| 属性名 | 类型 | 描述 | 默认值 |
|---|---|---|---|
placeholder | string | 阅读态空值占位符 | '-' |
PreviewText.Input
| 属性名 | 类型 | 描述 | 默认值 |
|---|---|---|---|
modelValue | any | 当前值 | - |
formatter | Function | 自定义文本格式化 | - |
其余 PreviewText.* 组件会复用对应表单组件的展示相关属性,例如 dataSource、columns、options、areaList、format、valueFormat、separator 和 displayFormatter。