Form 表单
承载数据录入、校验和提交,是业务系统里最核心的交互容器。
基础用法
等待提交
vue
<template>
<x-form :model="form" @submit="handleSubmit">
<x-form-item field="name" tooltip="用于展示在业务列表中" label="名称" required>
<x-input v-model="form.name" placeholder="请输入名称" />
</x-form-item>
<x-form-item field="post" label="职位">
<x-input v-model="form.post" placeholder="请输入职位" />
</x-form-item>
<x-form-item field="isRead">
<x-checkbox v-model="form.isRead">我已阅读并同意</x-checkbox>
</x-form-item>
<x-form-item>
<x-button type="primary" html-type="submit">提交</x-button>
</x-form-item>
</x-form>
</template>
<script setup lang="ts">
import { reactive } from 'vue';
const form = reactive({ name: '', post: '', isRead: false });
const handleSubmit = ({ values, errors }) => {
console.log(values, errors);
};
</script>布局
vue
<template>
<x-radio-group v-model="layout" type="button">
<x-radio value="horizontal">horizontal</x-radio>
<x-radio value="vertical">vertical</x-radio>
<x-radio value="inline">inline</x-radio>
</x-radio-group>
<x-form :model="form" :layout="layout">
<x-form-item field="name" label="用户名">
<x-input v-model="form.name" />
</x-form-item>
<x-form-item field="post" label="岗位">
<x-input v-model="form.post" />
</x-form-item>
</x-form>
</template>
<script setup lang="ts">
import { reactive, ref } from 'vue';
const layout = ref('horizontal');
const form = reactive({ name: '', post: '' });
</script>表单校验
点击提交查看校验结果
vue
<template>
<x-form ref="formRef" :model="form" :rules="rules" scroll-to-first-error @submit="handleSubmit">
<x-form-item field="name" label="用户名" :validate-trigger="['change', 'input']">
<x-input v-model="form.name" placeholder="至少 3 个字符" />
</x-form-item>
<x-form-item field="age" label="年龄">
<x-input-number v-model="form.age" :min="0" :max="200" />
</x-form-item>
<x-form-item field="section" label="部门">
<x-select v-model="form.section" :options="sectionOptions" allow-clear />
</x-form-item>
<x-form-item>
<x-button type="primary" html-type="submit">提交校验</x-button>
<x-button @click="formRef?.resetFields()">重置</x-button>
</x-form-item>
</x-form>
</template>
<script setup lang="ts">
import { reactive, ref } from 'vue';
const formRef = ref();
const form = reactive({ name: '', age: 18, section: '' });
const rules = {
name: [
{ required: true, message: '请输入用户名' },
{ minLength: 3, message: '用户名至少 3 个字符' },
],
age: [{ type: 'number', max: 120, message: '年龄不能超过 120' }],
section: [{ match: /section one/, message: '请选择 Section One' }],
};
const sectionOptions = [
{ label: 'Section One', value: 'section one' },
{ label: 'Section Two', value: 'section two' },
];
const handleSubmit = ({ values, errors }) => {
console.log(values, errors);
};
</script>表单方法
可手动触发表单方法
vue
<template>
<x-form ref="formRef" :model="form" :rules="rules">
<x-form-item field="username" label="用户名">
<x-input v-model="form.username" />
</x-form-item>
<x-form-item field="email" label="邮箱">
<x-input v-model="form.email" />
</x-form-item>
<x-form-item>
<x-button @click="formRef?.validate()">validate</x-button>
<x-button @click="setServerError">setFields</x-button>
<x-button @click="formRef?.clearValidate()">clearValidate</x-button>
<x-button @click="formRef?.resetFields()">resetFields</x-button>
</x-form-item>
</x-form>
</template>
<script setup lang="ts">
import { reactive, ref } from 'vue';
const formRef = ref();
const form = reactive({ username: '', email: '' });
const rules = {
username: [{ required: true, message: '请输入用户名' }],
email: [{ type: 'email', message: '邮箱格式不正确' }],
};
const setServerError = () => {
formRef.value?.setFields({
email: { status: 'error', message: '服务端返回:邮箱已被占用' },
});
};
</script>状态与反馈
vue
<template>
<x-form :model="form" :size="size">
<x-form-item
field="name"
label="名称"
help="当前状态由 validateStatus 手动控制"
extra="开启 feedback 后展示反馈图标"
:validate-status="status"
feedback
>
<x-input v-model="form.name" />
</x-form-item>
</x-form>
</template>
<script setup lang="ts">
import { reactive, ref } from 'vue';
const status = ref('success');
const size = ref('medium');
const form = reactive({ name: '' });
</script>全局禁用
vue
<template>
<x-form :model="form" disabled>
<x-form-item field="name" label="用户名">
<x-input v-model="form.name" />
</x-form-item>
<x-form-item field="isRead">
<x-checkbox v-model="form.isRead">已确认</x-checkbox>
</x-form-item>
</x-form>
</template>
<script setup lang="ts">
import { reactive } from 'vue';
const form = reactive({ name: 'Locked user', isRead: true });
</script>帮助信息和插槽
vue
<template>
<x-form :model="form">
<x-form-item field="name" required validate-trigger="input">
<template #label>
<span>登录名</span>
</template>
<x-input v-model="form.name" />
<template #extra>
<span>用于后台账号展示</span>
</template>
</x-form-item>
<x-form-item field="post" label="岗位" required>
<x-input v-model="form.post" />
<template #help>
<span>自定义帮助信息会展示在控件下方</span>
</template>
</x-form-item>
</x-form>
</template>
<script setup lang="ts">
import { reactive } from 'vue';
const form = reactive({ name: '', post: '' });
</script>嵌套字段
支持 user.name、members[0] 这类路径
vue
<template>
<x-form ref="formRef" :model="form" :rules="rules" @submit="handleSubmit">
<x-form-item field="user.name" label="姓名">
<x-input v-model="form.user.name" />
</x-form-item>
<x-form-item field="user.email" label="邮箱">
<x-input v-model="form.user.email" />
</x-form-item>
<x-form-item field="members" label="成员">
<x-select v-model="form.members" :options="memberOptions" multiple />
</x-form-item>
</x-form>
</template>
<script setup lang="ts">
import { reactive, ref } from 'vue';
const formRef = ref();
const form = reactive({
user: { name: '', email: '' },
members: ['pm'],
});
const rules = {
'user.name': [{ required: true, message: '请输入姓名' }],
'user.email': [{ type: 'email', message: '邮箱格式不正确' }],
members: [{ type: 'array', minLength: 2, message: '至少选择 2 个成员' }],
};
const memberOptions = [
{ label: '产品', value: 'pm' },
{ label: '设计', value: 'design' },
{ label: '前端', value: 'frontend' },
];
const handleSubmit = ({ values, errors }) => {
console.log(values, errors);
};
</script>按需导入
ts
import { Form, FormItem } from 'x-next';Form Props
| 参数 | 说明 | 类型 | 默认值 |
|---|---|---|---|
model | 表单数据对象 | Record<string, any> | 必填 |
layout | 表单布局 | 'horizontal' | 'vertical' | 'inline' | 'horizontal' |
size | 表单控件尺寸 | 'mini' | 'small' | 'medium' | 'large' | 跟随全局配置 |
labelColProps | 标签栅格配置 | object | { span: 5, offset: 0 } |
wrapperColProps | 控件栅格配置 | object | { span: 19, offset: 0 } |
labelColStyle | 标签列样式 | object | - |
wrapperColStyle | 控件列样式 | object | - |
labelAlign | 标签对齐方式 | 'left' | 'right' | 'right' |
disabled | 是否禁用整个表单 | boolean | undefined |
rules | 表单校验规则 | Record<string, FieldRule | FieldRule[]> | - |
autoLabelWidth | 自动计算标签宽度,仅水平布局生效 | boolean | false |
id | 表单 id 属性和表单控件 id 前缀 | string | - |
scrollToFirstError | 校验失败后滚动到第一个错误字段,可传滚动配置 | boolean | ScrollIntoViewOptions | false |
Form Events
| 事件名 | 说明 | 回调参数 |
|---|---|---|
submit | 表单提交时触发 | { values, errors }, event |
submit-success | 校验成功时触发 | values, event |
submit-failed | 校验失败时触发 | { values, errors }, event |
Form Methods
| 方法 | 说明 | 参数 |
|---|---|---|
validate | 校验全部表单数据 | (callback?) |
validateField | 校验指定字段 | (field, callback?) |
resetFields | 重置字段值和校验状态 | (field?) |
clearValidate | 清除字段校验状态 | (field?) |
setFields | 设置表单项值与状态 | (data) |
scrollToField | 滚动到指定字段 | (field, options?) |
FormItem Props
| 参数 | 说明 | 类型 | 默认值 |
|---|---|---|---|
field | 字段路径 | string | '' |
label | 标签文本 | string | - |
tooltip | 标签提示 | string | - |
showColon | 是否显示冒号 | boolean | false |
noStyle | 是否去除布局样式 | boolean | false |
disabled | 是否禁用当前项 | boolean | undefined |
help | 帮助文案 | string | - |
extra | 额外文案 | string | - |
required | 是否必填 | boolean | false |
asteriskPosition | 星号位置 | 'start' | 'end' | 'start' |
rules | 当前项校验规则 | FieldRule | FieldRule[] | - |
validateStatus | 手动指定校验状态 | 'success' | 'warning' | 'error' | 'validating' | - |
validateTrigger | 触发校验的事件 | 'change' | 'input' | 'focus' | 'blur' | string[] | 'change' |
labelColProps | 当前项标签列配置 | object | 继承 Form |
wrapperColProps | 当前项控件列配置 | object | 继承 Form |
hideLabel | 是否隐藏标签 | boolean | false |
hideAsterisk | 是否隐藏星号 | boolean | false |
labelColStyle | 标签列样式 | object | 继承 Form |
wrapperColStyle | 控件列样式 | object | 继承 Form |
rowProps | 当前项 Row 配置 | object | - |
rowClass | 当前项 Row class | string | array | object | - |
contentClass | 控件包裹层 class | string | array | object | - |
contentFlex | 内容层是否启用 flex | boolean | true |
mergeProps | 已废弃的子元素 props 合并控制 | boolean | function | true |
labelColFlex | 标签列 flex 宽度 | number | string | - |
feedback | 是否显示反馈图标 | boolean | false |
labelComponent | 标签渲染元素 | string | 'label' |
labelAttrs | 标签元素属性 | object | - |
FormItem Slots
| 插槽名 | 说明 |
|---|---|
default | 表单控件内容 |
label | 自定义标签 |
help | 自定义帮助信息 |
extra | 自定义额外内容 |