Skip to content

Latest commit

 

History

History

form

表单(Form)

由输入框、选择器、单选框、多选框等控件组成,用以收集、校验、提交数据

何时使用

  • 用于创建一个实体或收集信息。
  • 需要对输入的数据类型进行校验时。
  • 注意:当一个 form 元素中只有一个输入框时,在该输入框中按下回车应提交该表单。如果希望阻止这一默认行为,可以在 <vc-form> 标签上添加 @submit.native.prevent

典型表单

包括各种表单项,比如输入框、选择器、开关、单选框、多选框等。 在 Form 组件中,每一个表单域由一个 Form-Item 组件构成,表单域中可以放置各种类型的表单控件,包括 Input、Select、Checkbox、Radio、Switch、DatePicker、TimePicker。

:::RUNTIME

<template>
	<vc-form 
		ref="formValidate" 
		:model="formValidate" 
		:label-width="96"
		style="padding-left: 56px; margin-top: 21px"
		@submit.native.prevent
	>
		<vc-form-item label="input:">
			<vc-input v-model="formValidate.input" style="width: 300px" />
		</vc-form-item>
		<vc-form-item label="select:">
			<vc-select v-model="formValidate.select" style="width: 300px;" clearable>
				<vc-option
					v-for="(item, index) in cityList"
					:value="item.label"
					:key="index"
				>{{ item.label }}</vc-option>
			</vc-select>
		</vc-form-item>
		<vc-form-item label="switch:">
			<vc-switch v-model="formValidate.switch"/>
		</vc-form-item>
		<vc-form-item label="date:">
			<vc-date-picker 
				v-model="formValidate.date"
				type="datetime" 
				clearable
				placeholder="Select date" 
				style="width: 300px"
			/>
		</vc-form-item>
		<vc-form-item label="checkbox:">
			<vc-checkbox-group v-model="formValidate.checkbox">
				<vc-checkbox label="香蕉" />
				<vc-checkbox label="苹果" />
				<vc-checkbox label="西瓜" />
			</vc-checkbox-group>
		</vc-form-item>
		<vc-form-item label="radio:">
			<vc-radio-group v-model="formValidate.radio" vertical>
				<vc-radio label="金斑蝶" />
				<vc-radio label="爪哇犀牛" />
				<vc-radio label="印度黑羚" />
			</vc-radio-group>
		</vc-form-item>
		<vc-form-item label="radio:">
			<vc-radio-group v-model="formValidate.radio">
				<vc-radio label="金斑蝶" />
				<vc-radio label="爪哇犀牛" />
				<vc-radio label="印度黑羚" />
			</vc-radio-group>
		</vc-form-item>
		<vc-form-item
			v-for="(item, index) in formValidate.items"
			v-if="item.status"
			:key="index"
			:label="'Item ' + item.index + ':'"
			:prop="'items.' + index + '.value'"
			:rules="{required: true, message: 'Item ' + item.index +' can not be empty', trigger: 'change'}"
		>
			<span @click="handleRemove(index)">Delete</span>
		</vc-form-item>
		<vc-form-item>
			<div @click="handleAdd">
				Add item
			</div>
		</vc-form-item>
		<vc-form-item>
			<vc-button type="primary" @click="handleSubmit('formValidate')">
				Submit
			</vc-button>
			<vc-button style="margin-left: 8px" @click="handleReset('formValidate')">
				Reset
			</vc-button>
			<vc-button style="margin-left: 8px" @click="handleOnly('formValidate')">
				Only
			</vc-button>
		</vc-form-item>
	</vc-form>
</template>
<script>
import { Form, Input, Button, Checkbox, Radio, Select, Option, DatePicker, Switch } from '@wya/vc';

export default {
	name: "vc-form-basic",
	components: {
		'vc-form': Form,
		'vc-form-item': Form.Item,
		'vc-input': Input,
		'vc-select': Select,
		'vc-option': Option,
		'vc-date-picker': DatePicker,
		'vc-button': Button,
		'vc-checkbox-group': Checkbox.Group,
		'vc-checkbox': Checkbox,
		'vc-radio-group': Radio.Group,
		'vc-radio': Radio,
		'vc-switch': Switch,
	},
	data() {
		return {
			index: 1,
			formValidate: {
				input: '',
				select: '',
				switch: '',
				date: '',
				checkbox: [],
				radio: '',
				items: [{
					value: '',
					index: 1,
					status: 1
				}]
			},
			cityList: [{
				value: '1',
				label: 'New York'
			}, {
				value: '2',
				label: 'London'
			}]
		};
	},
	methods: {
		handleSubmit(name) {
			this.$refs[name].validate().then((res) => {

			}).catch((err) => {
				console.log(err);
			});
		},
		handleReset(name) {
			this.$refs[name].resetFields();
		},
		handleAdd() {
			this.index++;
			this.formValidate.items.push({
				value: '',
				index: this.index,
				status: 1
			});
		},
		handleOnly(name) {
			this.$refs[name].validateField('items.0.value', { scroll: true }).then(() => {

			}).catch((error) => {
				console.log(error);
			});
		},
		handleRemove(index) {
			this.formValidate.items[index].status = 0;
		}
	}
};
</script>
<style>
.v-form-basic {
	margin-bottom: 10px;
}
</style>

:::

行内表单

当垂直方向空间受限且表单较简单时,可以在一行内放置表单。 设置 inline 属性可以让表单域变为行内的表单域。

:::RUNTIME

<template>
	<vc-form 
		ref="formValidate" 
		:label-width="50"
		inline
		style="padding-left: 56px; margin-top: 21px"
		@submit.native.prevent
	>
		<vc-form-item label="input:">
			<vc-input v-model="formValidate.input" />
		</vc-form-item>
		<vc-form-item label="select:">
			<vc-select v-model="formValidate.select" clearable>
				<vc-option
					v-for="(item, index) in cityList"
					:value="item.label"
					:key="index"
				>{{ item.label }}</vc-option>
			</vc-select>
		</vc-form-item>
		<vc-form-item>
			<vc-button type="primary" @click="handleSubmit('formValidate')">
				Submit
			</vc-button>
		</vc-form-item>
	</vc-form>
</template>
<script>
import { Form, Input, Button, Select, Option } from '@wya/vc';

export default {
	name: "vc-form-basic",
	components: {
		'vc-form': Form,
		'vc-form-item': Form.Item,
		'vc-input': Input,
		'vc-select': Select,
		'vc-button': Button,
	},
	data() {
		return {
			formValidate: {
				input: '',
				select: '',
			},
			cityList: [{
				value: '1',
				label: 'New York'
			}, {
				value: '2',
				label: 'London'
			}]
		};
	},
	methods: {
		handleSubmit(name) {
			console.log(res, this.formValidate);
		},
	}
};
</script>
<style>
.v-form-basic {
	margin-bottom: 10px;
}
</style>

:::

对齐方式

根据具体目标和制约因素,选择最佳的标签对齐方式。 通过设置 label-position 属性可以改变表单域标签的位置,可选值为 topleft,当设为 top 时标签会置于表单域的顶部。

:::RUNTIME

<template>
	<div>
		<vc-radio-group v-model="labelPosition" type="button">
			<vc-radio label="left">左对齐</vc-radio>
			<vc-radio label="right">右对齐</vc-radio>
			<vc-radio label="top">顶部对齐</vc-radio>
		</vc-radio-group>
		<vc-form 
			ref="formValidate" 
			:label-width="50"
			:label-position="labelPosition"
			style="margin-top: 21px"
			@submit.native.prevent
		>
			<vc-form-item label="input:">
				<vc-input v-model="formValidate.input" style="width: 200px;" />
			</vc-form-item>
			<vc-form-item label="input:">
				<vc-input v-model="formValidate.input" style="width: 200px;" />
			</vc-form-item>
			<vc-form-item label="input:">
				<vc-input v-model="formValidate.input" style="width: 200px;" />
			</vc-form-item>
		</vc-form>
	</div>
</template>
<script>
import { Form, Input } from '@wya/vc';

export default {
	name: "vc-form-basic",
	components: {
		'vc-form': Form,
		'vc-form-item': Form.Item,
		'vc-input': Input,
	},
	data() {
		return {
			labelPosition: 'right',
			formValidate: {
				input: '',
			},
		};
	},
	methods: {
		handleSubmit(name) {
			console.log(res, this.formValidate);
		},
	}
};
</script>
<style>
.v-form-basic {
	margin-bottom: 10px;
}
</style>

:::

表单校验

在防止用户犯错的前提下,尽可能让用户更早地发现并纠正错误。 Form 组件提供了表单验证的功能,只需要通过 rules 属性传入约定的验证规则,并将 Form-Item 的 prop 属性设置为需校验的字段名即可。

:::RUNTIME

<template>
	<vc-form 
		ref="formValidate" 
		:model="formValidate" 
		:rules="ruleValidate"
		:label-width="96"
		style="padding-left: 56px; margin-top: 21px"
		@submit.native.prevent
	>
		<vc-form-item prop="input" label="input:">
			<vc-input v-model="formValidate.input" style="width: 300px" />
		</vc-form-item>
		<vc-form-item prop="select" label="select:">
			<vc-select v-model="formValidate.select" style="width: 300px;" clearable>
				<vc-option
					v-for="(item, index) in cityList"
					:value="item.label"
					:key="index"
				>{{ item.label }}</vc-option>
			</vc-select>
		</vc-form-item>
		<vc-form-item prop="switch" label="switch:">
			<vc-switch v-model="formValidate.switch"/>
		</vc-form-item>
		<vc-form-item prop="date" label="date:">
			<vc-date-picker 
				v-model="formValidate.date"
				type="datetime" 
				clearable
				placeholder="Select date" 
				style="width: 300px"
			/>
		</vc-form-item>
		<vc-form-item prop="checkbox" label="checkbox:">
			<vc-checkbox-group v-model="formValidate.checkbox">
				<vc-checkbox label="香蕉" />
				<vc-checkbox label="苹果" />
				<vc-checkbox label="西瓜" />
			</vc-checkbox-group>
		</vc-form-item>
		<vc-form-item prop="radio" label="radio:">
			<vc-radio-group v-model="formValidate.radio" vertical>
				<vc-radio label="金斑蝶" />
				<vc-radio label="爪哇犀牛" />
				<vc-radio label="印度黑羚" />
			</vc-radio-group>
		</vc-form-item>
		<vc-form-item prop="radio" label="radio:">
			<vc-radio-group v-model="formValidate.radio">
				<vc-radio label="金斑蝶" />
				<vc-radio label="爪哇犀牛" />
				<vc-radio label="印度黑羚" />
			</vc-radio-group>
		</vc-form-item>
		<vc-form-item
			v-for="(item, index) in formValidate.items"
			v-if="item.status"
			:key="index"
			:label="'Item ' + item.index + ':'"
			:prop="'items.' + index + '.value'"
			:rules="{required: true, message: 'Item ' + item.index +' can not be empty', trigger: 'change'}"
		>
			<span @click="handleRemove(index)">Delete</span>
		</vc-form-item>
		<vc-form-item>
			<div @click="handleAdd">
				Add item
			</div>
		</vc-form-item>
		<vc-form-item>
			<vc-button type="primary" @click="handleSubmit('formValidate')">
				Submit
			</vc-button>
			<vc-button style="margin-left: 8px" @click="handleReset('formValidate')">
				Reset
			</vc-button>
			<vc-button style="margin-left: 8px" @click="handleOnly('formValidate')">
				Only
			</vc-button>
		</vc-form-item>
	</vc-form>
</template>
<script>
import { Form, Input, Button, Checkbox, Radio, Select, Option, DatePicker, Switch } from '@wya/vc';

export default {
	name: "vc-form-basic",
	components: {
		'vc-form': Form,
		'vc-form-item': Form.Item,
		'vc-input': Input,
		'vc-select': Select,
		'vc-option': Option,
		'vc-date-picker': DatePicker,
		'vc-button': Button,
		'vc-checkbox-group': Checkbox.Group,
		'vc-checkbox': Checkbox,
		'vc-radio-group': Radio.Group,
		'vc-radio': Radio,
		'vc-switch': Switch,
	},
	data() {
		return {
			index: 1,
			formValidate: {
				input: '',
				select: '',
				switch: '',
				date: '',
				checkbox: [],
				radio: '',
				items: [
					{
						value: '',
						index: 1,
						status: 1
					}
				]
			},
			ruleValidate: {
				input: [
					{ required: true, message: '请输入内容', trigger: 'blur' },
           	 		{ min: 3, max: 5, message: '长度在 3 到 5 个字符', trigger: 'blur' }
				],
				select: [
					{ required: true, message: '请选择区域', trigger: 'change' }
				],
				date: [
					{ required: true, type: 'date', message: '请选择日期', trigger: 'change' }
				],
				checkbox: [
					{ type: 'array', required: true, message: '请至少选择一种水果', trigger: 'change' }
				],
				radio: [
					{ required: true, message: '请选择动物', trigger: 'change' }
				],
			},
			cityList: [
				{
					value: '1',
					label: 'New York'
				},
				{
					value: '2',
					label: 'London'
				}]
		};
	},
	methods: {
		handleSubmit(name) {
			this.$refs[name].validate().then((res) => {
			}).catch((err) => {
				console.log(err);
			});
		},
		handleOnly(name) {
			this.$refs[name].validateField('items.0.value', { scroll: true }).then(() => {
			}).catch((error) => {
				console.log(error);
			});
		},
		handleReset(name) {
			this.$refs[name].resetFields();
		},
		handleAdd() {
			this.index++;
			this.formValidate.items.push({
				value: '',
				index: this.index,
				status: 1
			});
		},
		handleRemove(index) {
			this.formValidate.items[index].status = 0;
		}
	}
};
</script>
<style>
.v-form-basic {
	margin-bottom: 10px;
}
</style>

:::

自定义校验规则

这个例子中展示了如何使用自定义验证规则来完成密码的二次验证。

:::RUNTIME

<template>
	<vc-form 
		ref="formValidate" 
		:model="formValidate" 
		:rules="ruleValidate"
		:label-width="96"
		style="padding-left: 56px; margin-top: 21px"
		@submit.native.prevent
	>
		<vc-form-item prop="pass" label="密码:">
			<vc-input type="password" v-model="formValidate.pass" style="width: 300px" />
		</vc-form-item>
		<vc-form-item prop="checkPass" label="确认密码:">
			<vc-input type="password" v-model="formValidate.checkPass" style="width: 300px" />
		</vc-form-item>
		<vc-form-item prop="age" label="年龄:">
			<vc-input v-model.number="formValidate.age" style="width: 300px" />
		</vc-form-item>
		<vc-form-item>
			<vc-button type="primary" @click="handleSubmit('formValidate')">
				Submit
			</vc-button>
			<vc-button style="margin-left: 8px" @click="handleReset('formValidate')">
				Reset
			</vc-button>
		</vc-form-item>
	</vc-form>
</template>
<script>
import { Form, Input, Button } from '@wya/vc';

export default {
	name: "vc-form-basic",
	components: {
		'vc-form': Form,
		'vc-form-item': Form.Item,
		'vc-input': Input,
		'vc-button': Button,
	},
	data() {
		const checkAge = (rule, value, callback) => {
			if (!value) {
				return callback(new Error('年龄不能为空'));
			}
			setTimeout(() => {
				if (!Number.isInteger(value)) {
					callback(new Error('请输入数字值'));
				} else {
					if (value < 18) {
						callback(new Error('必须年满18岁'));
					} else {
						callback();
					}
				}
			}, 1000);
		};
		const validatePass = (rule, value, callback) => {
			if (!value) {
				callback(new Error('请输入密码'));
			} else {
				if (!this.formValidate.checkPass) {
					this.$refs.formValidate.validateField('checkPass');
				}
				callback();
			}
		};
		const validatePass2 = (rule, value, callback) => {
			if (!value) {
				callback(new Error('请再次输入密码'));
			} else if (value !== this.formValidate.pass) {
				callback(new Error('两次输入密码不一致!'));
			} else {
				callback();
			}
		};
		return {
			formValidate: {
				pass: '',
          		checkPass: '',
				age: ''
			},
			ruleValidate: {
				pass: [
					{ validator: validatePass, trigger: 'blur' }
				],
				checkPass: [
					{ validator: validatePass2, trigger: 'blur' }
				],
				age: [
					{ validator: checkAge, trigger: 'blur' }
				]
			},
		};
	},
	methods: {
		handleSubmit(name) {
			this.$refs[name].validate(() => {}).then((res) => {

			}).catch((res) => {
				console.log(res, this.formValidate);
			});
		},
		handleReset(name) {
			this.$refs[name].resetFields();
		},
	}
};
</script>
<style>
.v-form-basic {
	margin-bottom: 10px;
}
</style>

:::

API

属性

属性 说明 类型 可选值 默认值
model 表单数据对象 Object - -
rules 表单验证规则,具体配置查看 async-validator Object - -
inline 是否开启行内表单模式 Boolean - false
label-position 表单域标签的位置 String leftrighttop right
label-width 表单域标签的宽度,所有的 FormItem 都会继承 Form 组件的 label-width 的值 Number - -
show-message 是否显示校验错误信息 Boolean - true
autocomplete 原生的 autocomplete 属性 String offon off

方法

方法名 说明 参数
validate 对整个表单进行校验,参数为检验完的回调,会返回一个 Boolean 表示成功与失败,支持 Promise -
validateField 对部分表单字段进行校验的方法 props: 需校验的 prop; callback: 检验完回调,返回错误信息
resetFields 对整个表单进行重置,将所有字段值重置为空并移除校验结果 -

Item 属性

属性 说明 类型 可选值 默认值
prop 对应表单域 model 里的字段 String - -
label 标签文本 String - -
label-width 表单域标签的的宽度 Number -
label-for 指定原生的 label 标签的 for 属性,配合控件的 element-id 属性,可以点击 label 时聚焦控件。 String - -
required 是否必填,如不设置,则会根据校验规则自动生成 Boolean - -
rules 表单验证规则 Object Array -
error 表单域验证错误信息, 设置该值会使表单验证状态变为error,并显示该错误信息 String - -
show-message 是否显示校验错误信息 Boolean - true

Item Slot

属性 说明
label label 内容