Skip to content
# t-form

Form 表单

t-form 组件介绍 ​

表单组件,支持表单验证规则后端控制,支持form-item点击映射到input获取到焦点提升用户体验,支持表单下任意组件参与布局,支持自定义函数表单验证,支持自定义数据校验、长度校验证、数据大小判断,支持重置。

t-form 平台兼容 ​

HarmonyH5AndroidiOS小程序UTS
✅✅✅✅✅✅

t-form 基础用法 ​

vue
<template>
	<view class="p-15">
		<tui-theme-switch></tui-theme-switch>
		<t-card title="Form 表单"
				class="mb-15"
				sub-title="支持自定义数据校验,长度校验证,数据大小判断 支持重置 支持表单下任意组件参与布局,支持自定义函数表单验证"></t-card>
		<t-form :class="[`r-10 ov tvg`]"
				:disabled="disabled"
				ref="ruleForm"
				:rules="rules"
				child-class="ptb-10"
				:model="formData"
				direction="row">
			<t-form-item label="活动名称"
						 prop="name">
				<t-input v-model="(formData.name as string)"
						 input-class="sta-r"
						 class="f pr-0 bgn"
						 placeholder="请输入活动名称"
						 effect=""></t-input>
			</t-form-item>
			<t-form-item label="活动区域"
						 prop="region">
				<t-radio-group v-model="(formData.region as string)"
							   class="f fl fww fjce"
							   child-class="p-0 ml-5">
					<t-radio v-for="(item,index) in regionList"
							 :key="index"
							 :value="`${index}`"
							 type="primary">{{item}}
					</t-radio>
				</t-radio-group>
			</t-form-item>
			<t-form-item label="活动产品"
						 prop="checkbox">
				<t-checkbox-group :class="`f fl fww fjce`"
								  type="primary"
								  v-model="(formData.checkbox as string[])"
								  child-class="p-0 ml-8"
								  :transition="false">
					<t-checkbox value="1">苹果</t-checkbox>
					<t-checkbox value="2">香蕉</t-checkbox>
				</t-checkbox-group>
			</t-form-item>
			<t-form-item label="验证码"
						 prop="tcodeinput">
				<t-code-input class=""
							  v-model="(formData.tcodeinput as string)"
							  type="primary"
							  dotSymbol=""
							  :maxlength="4"></t-code-input>
			</t-form-item>
			<t-form-item label="手机号(自定义函数校验测试)"
						 prop="phone"
						 direction="column">
				<t-input v-model="(formData.phone as string)"
						 :maxlength="11"
						 class="p-10 r-10 fww"
						 placeholder="请输入手机号"></t-input>
			</t-form-item>
			<t-form-item label="评分"
						 prop="trate">
				<t-rate v-model="(formData.trate as number)"
						icon-class="s-30!"
						type="primary"></t-rate>
			</t-form-item>
			<t-form-item label="开关"
						 prop="tswitch">
				<t-switch v-model="(formData.tswitch as boolean)"
						  type="primary"
						  activeIcon="volume-up"
						  inactiveIcon="volume-off"></t-switch>
			</t-form-item>
			<t-form-item label="图片上传"
						 prop="tupload">
				<t-upload v-model="(formData.tupload as string[])"
						  size="large"
						  :count="1"></t-upload>
			</t-form-item>
			<t-form-item label="Select"
						 prop="pickerselectval">
				<t-picker-select v-model="(formData.pickerselectval as string)"
								 :list="selectlist"
								 valueKey="value"
								 labelKey="label"
								 class="f">
				</t-picker-select>
			</t-form-item>
			<t-form-item label="步进器"
						 prop="tnumberbox"
						 class="ov">
				<t-stepper v-model="(formData.tnumberbox as number)"
						   type="success"></t-stepper>
			</t-form-item>
			<t-form-item label="slider"
						 prop="slider">
				<t-slider class="f h-80"
						  direction="horizontal"
						  :min="0"
						  :max="500"
						  type="primary"
						  blockSize="30"
						  :disabled="false"
						  :showValue="true"
						  trackSize="10"
						  v-model="(formData.slider as number[])"
						  showMode="before" />
			</t-form-item>
			<t-form-item label="颜色选择器"
						 prop="color"
						 :bottomLine="false"
						 direction="row">
				<t-color v-model="(formData.color as string)"></t-color>
			</t-form-item>
			<t-form-item label="活动时间"
						 prop="activityTime">
				<t-select-date class="f"
							   v-model="(formData.activityTime as string)"
							   format="yyyy-mm-dd">
				</t-select-date>
			</t-form-item>
			<t-form-item label="活动地点"
						 prop="pca">
				<t-picker-city :list="list"
							   v-model="(formData.pca as string[])">
				</t-picker-city>
			</t-form-item>
			<t-form-item label="活动内容"
						 prop="textarea"
						 :bottomLine="false"
						 direction="col">
				<t-textarea placeholder="请输入活动内容"
							v-model="(formData.textarea as string)"
							effect="plain"
							:border="true"></t-textarea>
			</t-form-item>
			<t-form-item label="弹窗日历"
						 prop="calendar1">
				<t-picker-calendar mode="single"
								   :vertical="false"
								   class="f"
								   v-model="(formData.calendar1 as string[])">
				</t-picker-calendar>
			</t-form-item>
			<t-form-item label="级联表单"
						 prop="cascader"
						 direction="col"
						 :show-label="false">
				<t-cascader v-model="(formData.cascader as string[])"
							type="p"
							:option="cascaderlist"></t-cascader>
			</t-form-item>
			<t-form-item label="文件选择"
						 prop="filemanager"
						 direction="col"
						 :show-label="false">
				<t-file-manager type="primary"
								v-model="formData.filemanager"
								class=""></t-file-manager>
			</t-form-item>
		</t-form>

		<t-button class="mb-15"
				  type="primary"
				  @click="submitForm">提交</t-button>
		<t-button class="mb-15"
				  type="success"
				  @click="resetForm">重置</t-button>
		<t-button type="error"
				  @click="disabled = !disabled">{{ disabled ? '取消禁用' : '禁用表单' }}</t-button>
	</view>
</template>

<script setup>
	import { ref, reactive, ComponentPublicInstance } from 'vue'
	import { TuiApi } from '@/api'
	import { isPhone } from "@/uni_modules/tui-common"
	type SelectOptions = {
		value : string
		label : string
		disabled ?: boolean
	}
	const disabled = ref(false)
	const list = ref<UTSJSONObject[]>([])
	const regionList = ref(['北京', '上海', '重庆'])
	const activeTitle = ref('请选择活动时间')
	const calendarTitle = ref('请选择日历')
	const calendarOpen = ref(false)
	const loadings = ref(false)
	const citys = ref<string[]>([])
	// 表单数据对象(使用reactive确保深度响应)
	const formData = reactive({
		name: '',
		desc: '',
		region: '',
		activityTime: '',
		checkbox: [] as string[],
		tcodeinput: '',
		tnumberbox: 4,
		trate: 0,
		tswitch: true,
		tupload: [] as string[],
		tselectval: [] as string[],
		calendar: ['2025-3-18', '2025-3-28'],
		calendar1: [] as string[],
		pca: [] as string[],
		school: [] as string[],
		textarea: '',
		slider: [10, 60, 300],
		color: '#f56c6c',
		phone: '',
		cascader: [] as string[],
		filemanager: [] as UTSJSONObject[],
		pickerselectval: ''
	})

	const fiellist = ref([{ name: '驾驶证' }, { name: '身份证' }])
	const fiellist1 = ref([{ name: '合同一' }, { name: '合同二' }])

	const selectlist = ref([
		{ value: '选项1', label: '黄金糕' },
		{ value: '选项2', label: '双皮奶', disabled: true },
		{ value: '选项3', label: '蚵仔煎' },
		{ value: '选项4', label: '龙须面' },
		{ value: '选项5', label: '北京烤鸭' }
	])

	const selectOptions = ref<SelectOptions[]>([
		{ value: '选项1', label: '黄金糕' },
		{ value: '选项2', label: '双皮奶', disabled: true },
		{ value: '选项3', label: '蚵仔煎' },
		{ value: '选项4', label: '龙须面' },
		{ value: '选项5', label: '北京烤鸭' }
	])

	// 表单校验规则(保持原样)
	const rules = reactive<UTSJSONObject>({
		school: [{ type: 'required', message: '院系不能为空' }],
		phone: [
			{ type: 'required', message: '手机号不能为空' },
			{
				type: 'function',
				fun: (e : any) : boolean => {
					return isPhone(`${e}`)
				},
				message: '手机号正则验证失败'
			}
		],
		name: [
			{ type: 'required', message: '请输入活动名称' },
			{ type: 'length', min: 3, max: 5, message: '字符串长度必须为3-5之间' }
		],
		trate: [{ type: 'range', min: 3, max: 5, message: '评分必须为3-5分' }],
		tupload: [{ type: 'required', message: '图片上传不能为空' }],
		tselectval: [{ type: 'required', message: '输入不能为空' }],
		pickerselectval: [{ type: 'required', message: '选择内容不能为空' }],
		pca: [{ type: 'required', message: '请选择活动地点' }],
		textarea: [{ type: 'required', message: '活动内容不能为空' }],
		slider: [{ type: 'required', message: 'slider验证失败' }],
		color: [{ type: 'required', message: '请选择颜色' }],
		tswitch: [{ type: 'required', message: 'switch校验必填为空' }],
		calendar: [{ type: 'required', message: '日历数据不能为空' }],
		filemanager: [{ type: 'required', message: '请选择文件内容' }],
		calendar1: [{ type: 'required', message: '日历数据不能为空' }],
		cascader: [{ type: 'required', message: '请选择级联数据' }],
		tcodeinput: [{ type: 'required', message: '验证码不能为空' }],
		desc: [{ type: 'required', message: '请选择活动区域' }],
		tnumberbox: [
			{ type: 'required', message: '步进必填验证不能为空' },
			{ type: 'range', min: 3, max: 5, message: '表单验证为3-5之间' }
		],
		checkbox: [{ type: 'required', message: 'checkbox不能为空' }],
		region: [{ type: 'required', message: '请选择活动区域' }],
		activityTime: [{ type: 'required', message: '请选择日期' }]
	})

	const selected = ref([
		{
			date: '2025-3-17',
			info: '打折',
			infoColor: '#00cc81',
			badge: true,
			badgeInfo: '休',
			badgeColor: '#ff0000',
			disabled: true
		},
	])

	const cascaderlist = ref([
		{
			"value": "zhinan",
			"label": "指南",
			"children": [
				{
					"value": "shejiyuanze",
					"label": "设计原则",
					"children": [
						{
							"value": "yizhi",
							"label": "一致",
							"disabled": true
						},
						{
							"value": "fankui",
							"label": "反馈"
						},
						{
							"value": "xiaolv",
							"label": "效率"
						},
						{
							"value": "kekong",
							"label": "可控"
						}
					]
				},
				{
					"value": "daohang",
					"label": "导航",
					"children": [
						{
							"value": "cexiangdaohang",
							"label": "侧向导航"
						},
						{
							"value": "dingbudaohang",
							"label": "顶部导航"
						}
					]
				}
			]
		},
		{
			"value": "zujian",
			"label": "组件",
			"children": [
				{
					"value": "basic",
					"label": "Basic",
					"children": [
						{
							"value": "layout",
							"label": "Layout 布局"
						},
						{
							"value": "color",
							"label": "Color 色彩"
						},
						{
							"value": "typography",
							"label": "Typography 字体"
						},
						{
							"value": "icon",
							"label": "Icon 图标"
						},
						{
							"value": "button",
							"label": "Button 按钮"
						}
					]
				},
				{
					"value": "form",
					"label": "Form",
					"children": [
						{
							"value": "radio",
							"label": "Radio 单选框"
						},
						{
							"value": "checkbox",
							"label": "Checkbox 多选框"
						},
						{
							"value": "input",
							"label": "Input 输入框"
						},
						{
							"value": "input-number",
							"label": "InputNumber 计数器"
						},
						{
							"value": "select",
							"label": "Select 选择器"
						},
						{
							"value": "cascader",
							"label": "Cascader 级联选择器"
						},
						{
							"value": "switch",
							"label": "Switch 开关"
						},
						{
							"value": "slider",
							"label": "Slider 滑块"
						},
						{
							"value": "time-picker",
							"label": "TimePicker 时间选择器"
						},
						{
							"value": "date-picker",
							"label": "DatePicker 日期选择器"
						},
						{
							"value": "datetime-picker",
							"label": "DateTimePicker 日期时间选择器"
						},
						{
							"value": "upload",
							"label": "Upload 上传"
						},
						{
							"value": "rate",
							"label": "Rate 评分"
						},
						{
							"value": "form",
							"label": "Form 表单"
						}
					]
				},
				{
					"value": "data",
					"label": "Data",
					"children": [
						{
							"value": "table",
							"label": "Table 表格"
						},
						{
							"value": "tag",
							"label": "Tag 标签"
						},
						{
							"value": "progress",
							"label": "Progress 进度条"
						},
						{
							"value": "tree",
							"label": "Tree 树形控件"
						},
						{
							"value": "pagination",
							"label": "Pagination 分页"
						},
						{
							"value": "badge",
							"label": "Badge 标记"
						}
					]
				},
				{
					"value": "notice",
					"label": "Notice",
					"children": [
						{
							"value": "alert",
							"label": "Alert 警告"
						},
						{
							"value": "loading",
							"label": "Loading 加载"
						},
						{
							"value": "message",
							"label": "Message 消息提示"
						},
						{
							"value": "message-box",
							"label": "MessageBox 弹框"
						},
						{
							"value": "notification",
							"label": "Notification 通知"
						}
					]
				},
				{
					"value": "navigation",
					"label": "Navigation",
					"children": [
						{
							"value": "menu",
							"label": "NavMenu 导航菜单"
						},
						{
							"value": "tabs",
							"label": "Tabs 标签页"
						},
						{
							"value": "breadcrumb",
							"label": "Breadcrumb 面包屑"
						},
						{
							"value": "dropdown",
							"label": "Dropdown 下拉菜单"
						},
						{
							"value": "steps",
							"label": "Steps 步骤条"
						}
					]
				},
				{
					"value": "others",
					"label": "Others",
					"children": [
						{
							"value": "dialog",
							"label": "Dialog 对话框"
						},
						{
							"value": "tooltip",
							"label": "Tooltip 文字提示"
						},
						{
							"value": "popover",
							"label": "Popover 弹出框"
						},
						{
							"value": "card",
							"label": "Card 卡片"
						},
						{
							"value": "carousel",
							"label": "Carousel 走马灯"
						},
						{
							"value": "collapse",
							"label": "Collapse 折叠面板"
						}
					]
				}
			]
		},
		{
			"value": "ziyuan",
			"label": "资源",
			"children": [
				{
					"value": "axure",
					"label": "Axure Components"
				},
				{
					"value": "sketch",
					"label": "Sketch Templates"
				},
				{
					"value": "jiaohu",
					"label": "组件交互文档"
				}
			]
		}
	])

	const ruleForm = ref<ComponentPublicInstance | null>(null)

	const dateConfirm = (e : UTSJSONObject) => {
		formData.activityTime = e.getString('time')!
	}

	const cityConfirm = (e : any) => {
	}

	const colorConfirm = (e : any) => {
		formData.color = e.hex
	}

	const calendarConfirm = (e : string[]) => {
		if (e.length > 0) calendarTitle.value = e[0]
	}

	const submitForm = () => {
		const validate = ruleForm.value?.$callMethod('validate') as boolean
		if (validate) {
			console.log(formData)
			uni.showModal({ title: '数据提交成功' })
			disabled.value = !disabled.value
		} else {
			uni.showModal({ title: '数据校验失败' })
		}
	}

	const resetForm = () => {
		ruleForm.value?.$callMethod('reset')
	}

	onLoad(() => {
		TuiApi('citydata', {}, false).then(res => {
			list.value = res.getArray('data') as UTSJSONObject[]
		})
	})
</script>

t-form Props ​

属性名类型默认值说明可选值
sizeString""组件尺寸large, medium, small, mini
typeString""组件类型info, primary, error, warning, success
disabledBooleanfalse组件是否禁用true, false
hoverBooleanfalse是否有点击效果true, false
pathString""点击组件后跳转的页面路径-
effectString""组件显示主题normal, dark, light, plain
showLabelBooleantrue统一设置表单子组合是否显示标题true, false
headerClassString""标题盒子的样式-
directionString"row"统一设置表单子项的布局方向row, column
rulesObject{}表单的验证规则-
rulesClassString""验证失败提示文字的样式-
labelClassString""标题标签的样式-
childClassString""统一设置子组件样式-
requiredAsteriskString"*"必填时的提示符-
requiredAsteriskClassString"mt-10"必填提示符的样式-
hideRequiredAsteriskBooleanfalse是否隐藏必填文本true, false
showMessageBooleantrue是否显示验证信息true, false
bottomLineBooleanfalse是否显示底部线条true, false
modelObject{}表单绑定的对象-

t-form Events ​

事件名说明回调参数
click点击时触发-
transitionend动画结束时触发-
initFinished组件初始化完成触发组件的节点信息
touchstart触摸开始时触发触摸事件对象
touchend触摸结束时触发触摸事件对象
touchmove触摸移动时触发触摸事件对象
touchcancel触摸取消时触发触摸事件对象
reset重置表单时触发-

Methods ​

方法名说明参数返回值
validate验证表单无Boolean
reset重置表单无无

t-form Slots ​

插槽名说明
default表单内容插槽,用于放置t-form-item子组件

校验规则 ​

规则类型说明示例
required必填{ required: true, message: '请输入用户名' }
min最小长度{ min: 6, message: '长度至少6位' }
max最大长度{ max: 20, message: '长度最多20位' }
pattern正则表达式{ pattern: /^1[3-9]\d{9}$/, message: '手机号格式错误' }
type数据类型{ type: 'email', message: '邮箱格式错误' }
validator自定义验证函数{ validator: (rule, value) => value > 0, message: '必须大于0' }