Element表单校验
作为一个后端开发,总结一下实际工作中表单校验的场景和用法。
Element官网:https://element.eleme.cn/#/zh-CN/component/form
代码地址:https://gitee.com/kkmy/kw-microservices/tree/master/kw-ui/kwsphere
常用表单校验场景
- 表单基本校验(长度、非空、数字类型、金额类型)
- 嵌套对象校验 (字段较多,存在嵌套对象,使用同一个el-form)
- 字段联动校验 (审核场景,同意则审核意见置为非必输)
- 自定义校验函数 (金额类型的长度校验,身份满18岁校验)
- 重置表单、校验指定表单、校验指定字段(element表单常用方法)
- 动态列表表单(添加多条配置)
- 文件校验 (element上传组件)
- 多表单el-form提交校验
场景使用Demo
表单基本校验
<template><div class="container"><div class="center-container"><el-form :model="userForm" :rules="rules" ref="userForm" label-width="100px"class="demo-userForm"><el-form-item label="姓名" prop="name"><el-input v-model="userForm.name"></el-input></el-form-item><el-form-item label="性别" prop="gender"><el-radio-group v-model="userForm.gender"><el-radio label="男"></el-radio><el-radio label="女"></el-radio></el-radio-group></el-form-item><!--中国行政区划代码:https://www.mca.gov.cn/n156/n186/c110746/content.html--><el-form-item label="籍贯" prop="nativePlace"><el-select v-model="userForm.nativePlace" placeholder="请选择性别"><el-option value="110000" label="北京市"></el-option><el-option value="120000" label="天津市"></el-option></el-select></el-form-item><el-form-item label="管理员" prop="admin"><el-switch v-model="userForm.admin"></el-switch></el-form-item><el-form-item label="爱好" prop="hobby"><el-checkbox-group v-model="userForm.hobby"><el-checkbox label="骑行" name="hobby"></el-checkbox><el-checkbox label="跑步" name="hobby"></el-checkbox><el-checkbox label="网游" name="hobby"></el-checkbox><el-checkbox label="旅行" name="hobby"></el-checkbox></el-checkbox-group></el-form-item><el-form-item label="个性签名" prop="desc"><el-input type="textarea" v-model="userForm.desc"></el-input></el-form-item><el-form-item><el-button type="primary" @click="submitForm('userForm')">保 存</el-button><el-button @click="resetForm('userForm')">重 置</el-button></el-form-item></el-form></div><el-dialogtitle="提示":visible.sync="centerDialogVisible"width="30%"@close="closeDialog":close-on-click-modal="false":close-on-press-escape="false"center><span><pre>{{userForm}}</pre></span><span slot="footer" class="dialog-footer"><el-button @click="centerDialogVisible = false">取 消</el-button><el-button type="primary" @click="centerDialogVisible = false">确 定</el-button></span></el-dialog></div>
</template><script>
export default {name: "validate-01",data() {return {userForm: {name: '',nativePlace: '',admin: false,hobby: [],gender: '',desc: ''},rules: {name: [{required: true, message: '请输入姓名', trigger: ['blur', 'change']},{min: 2, max: 5, message: '长度在 3 到 5 个字符', trigger: 'blur'}],nativePlace: [{required: true, message: '请选择籍贯', trigger: 'blur'}],hobby: [{type: 'array', required: true, message: '请至少选择一个爱好', trigger: 'change'},{type: 'array', min: 2, message: '请至少选择2个爱好', trigger: 'change'},],gender: [{required: true, message: '请选择性别', trigger: 'change'}],desc: [{required: true, message: '请填写个性签名', trigger: 'blur'},{max: 200, message: '个性签名长度不能大于200', trigger: 'blur'},]},centerDialogVisible: false,};},methods: {closeDialog() {this.centerDialogVisible = false;this.$refs.userForm.resetFields();},submitForm(formName) {this.$refs.userForm.validate((valid) => {if (valid) {this.centerDialogVisible = true;} else {console.log('error submit!!');return false;}});},resetForm(formName) {//this.$refs[formName].resetFields();this.$refs.userForm.resetFields();}}
}
</script><style scoped>
.container {display: flex;justify-content: center;align-items: center;height: 100vh; /* 设置父容器的高度为视口高度,使其充满整个屏幕 */
}.center-container {max-width: 600px; /* 设置内部容器的最大宽度,根据需求进行调整 */
}
</style>
嵌套对象校验
<template><div class="container"><div class="center-container"><el-form :model="userForm" :rules="rules" ref="userForm" label-width="100px"class="demo-userForm"><span>基本信息:</span><br><el-form-item label="姓名" prop="name"><el-input v-model="userForm.name"></el-input></el-form-item><el-form-item label="性别" prop="gender"><el-radio-group v-model="userForm.gender"><el-radio label="男"></el-radio><el-radio label="女"></el-radio></el-radio-group></el-form-item><el-form-item label="籍贯" prop="nativePlace"><el-select v-model="userForm.nativePlace" placeholder="请选择性别"><el-option value="110000" label="北京市"></el-option><el-option value="120000" label="天津市"></el-option></el-select></el-form-item><span>联系方式:</span><br><el-form-item label="QQ" prop="contactDetails.qq"><el-input v-model="userForm.contactDetails.qq"></el-input></el-form-item><el-form-item label="微信" prop="contactDetails.wx"><el-input v-model="userForm.contactDetails.wx"></el-input></el-form-item><el-form-item label="手机号" prop="contactDetails.phone"><el-input v-model="userForm.contactDetails.phone"></el-input></el-form-item><el-form-item><el-button type="primary" @click="submitForm('userForm')">保 存</el-button><el-button @click="resetForm('userForm')">重 置</el-button></el-form-item></el-form></div><el-dialogtitle="提示":visible.sync="centerDialogVisible"width="30%"@close="closeDialog":close-on-click-modal="false":close-on-press-escape="false"center><span><pre>{{ userForm }}</pre></span><span slot="footer" class="dialog-footer"><el-button @click="centerDialogVisible = false">取 消</el-button><el-button type="primary" @click="centerDialogVisible = false">确 定</el-button></span></el-dialog></div>
</template><script>
export default {name: "validate-01",data() {return {userForm: {name: '',nativePlace: '',gender: '',contactDetails: {qq: '',wx: '',phone: ''}},rules: {name: [{required: true, message: '请输入姓名', trigger: ['blur', 'change']},{min: 2, max: 5, message: '长度在 3 到 5 个字符', trigger: 'blur'}],nativePlace: [{required: true, message: '请选择籍贯', trigger: 'blur'}],gender: [{required: true, message: '请选择籍贯', trigger: 'change'}],'contactDetails.qq': [{required: true, message: '请输入联系方式qq', trigger: ['blur', 'change']},],'contactDetails.wx': [{required: true, message: '请输入联系方式微信', trigger: ['blur', 'change']},],'contactDetails.phone': [{required: true, message: '请输入联系方式手机号', trigger: ['blur', 'change']},],},centerDialogVisible: false,};},methods: {closeDialog() {this.centerDialogVisible = false;this.$refs.userForm.resetFields();},submitForm(formName) {this.$refs.userForm.validate((valid) => {if (valid) {this.centerDialogVisible = true;} else {console.log('error submit!!');return false;}});},resetForm(formName) {//this.$refs[formName].resetFields();this.$refs.userForm.resetFields();}}
}
</script><style scoped>
.container {display: flex;justify-content: center;align-items: center;height: 100vh; /* 设置父容器的高度为视口高度,使其充满整个屏幕 */
}.center-container {max-width: 600px; /* 设置内部容器的最大宽度,根据需求进行调整 */
}
</style>
字段联动校验
<template><div class="container"><div class="center-container"><el-form :model="userForm" :rules="rules" ref="userForm" label-width="100px"class="demo-userForm"><el-form-item label="审核结果" prop="result"><el-radio-group v-model="userForm.result" @change="clearValidate"><el-radio-button label="1">通过</el-radio-button><el-radio-button label="0">不通过</el-radio-button></el-radio-group></el-form-item><el-form-item label="审核意见" prop="desc":rules="[{required: userForm.result!=1, message: '请填写审核意见', trigger: 'blur'},{max: 200, message: '审核意见长度不能大于200', trigger: 'blur'}]"><el-input type="textarea" v-model="userForm.desc"></el-input></el-form-item><el-form-item><el-button type="primary" @click="submitForm('userForm')">保 存</el-button><el-button @click="resetForm('userForm')">重 置</el-button></el-form-item></el-form></div><el-dialogtitle="提示":visible.sync="centerDialogVisible"width="30%"@close="closeDialog":close-on-click-modal="false":close-on-press-escape="false"center><span><pre>{{ userForm }}</pre></span><span slot="footer" class="dialog-footer"><el-button @click="centerDialogVisible = false">取 消</el-button><el-button type="primary" @click="centerDialogVisible = false">确 定</el-button></span></el-dialog></div>
</template><script>
export default {name: "validate-01",data() {return {userForm: {result: '1',desc: ''},rules: {result: [{required: true, message: '请选择审核结果', trigger: 'change'}],},centerDialogVisible: false,};},methods: {closeDialog() {this.centerDialogVisible = false;this.$refs.userForm.resetFields();},clearValidate(val) {if (val == 1) {this.$refs.userForm.clearValidate('desc')}},submitForm(formName) {this.$refs.userForm.validate((valid) => {if (valid) {this.centerDialogVisible = true;} else {console.log('error submit!!');return false;}});},resetForm(formName) {//this.$refs[formName].resetFields();this.$refs.userForm.resetFields();}}
}
</script><style scoped>
.container {display: flex;justify-content: center;align-items: center;height: 100vh; /* 设置父容器的高度为视口高度,使其充满整个屏幕 */
}.center-container {max-width: 600px; /* 设置内部容器的最大宽度,根据需求进行调整 */
}
</style>
自定义校验函数
<template><div class="container"><div class="center-container"><el-form :model="userForm" :rules="rules" ref="userForm" label-width="100px"class="demo-userForm"><el-form-item label="提现金额" prop="amt"><el-input v-model="userForm.amt"></el-input></el-form-item><el-form-item label="证件类型" prop="idCardType"><el-select v-model="userForm.idCardType" placeholder="请选择证件类型"><el-option value="1" label="居民身份证"></el-option><el-option value="2" label="护照"></el-option></el-select></el-form-item><el-form-item label="证件号" prop="idCard"><el-input v-model="userForm.idCard"></el-input></el-form-item><el-form-item><el-button type="primary" @click="submitForm('userForm')">保 存</el-button><el-button @click="resetForm('userForm')">重 置</el-button></el-form-item></el-form></div><el-dialogtitle="提示":visible.sync="centerDialogVisible"width="30%"@close="closeDialog":close-on-click-modal="false":close-on-press-escape="false"center><span><pre>{{ userForm }}</pre></span><span slot="footer" class="dialog-footer"><el-button @click="centerDialogVisible = false">取 消</el-button><el-button type="primary" @click="centerDialogVisible = false">确 定</el-button></span></el-dialog></div>
</template><script>
import {cardid} from "@/utils/validate";export default {name: "validate-01",data() {let checkAmt = (rule, value, callback) => {if (value === '' || value === null) {callback(new Error('请输入提现金额'));} else if (value > 9999999.99) {//金额总长度不能大于10,包含小数点 value.toString().length > 10//数据库存储的类型为decimal(10,2),所以值不能大于9999999.99callback(new Error('提现金额不能大于9999999.99'));} else {callback();}}let checkIdCard = (rule, value, callback) => {if (!this.userForm.idCardType) {this.$refs.userForm.validateField('idCardType');} else {let idCardType = this.userForm.idCardType;if (idCardType == 1) {//居民身份证console.log(cardid(value))if (!cardid(value)[0]) {//todo 校验未成年callback();} else {callback(new Error(cardid(value)[1]))}} else if (idCardType == 2) {//护照let pattern = /^[a-zA-Z0-9]{3,20}$/;if (!pattern.test(value)) {callback(new Error("护照格式错误"))}} else {callback();}}}return {userForm: {idCard: '',idCardType: '',amt: '',},rules: {amt: [{required: true, message: '请输入提现金额', trigger: ['blur', 'change']},{pattern: /^\d+(\.\d{1,2})?$/, message: '金额格式错误', trigger: ['blur', 'change']},{validator: checkAmt, trigger: ['blur', 'change']}],idCardType: [{required: true, message: '请选择证件类型', trigger: ['blur']},],idCard: [{required: true, message: '请输入证件号', trigger: ['blur', 'change']},{validator: checkIdCard, trigger: ['blur', 'change']}],},centerDialogVisible: false,};},methods: {closeDialog() {this.centerDialogVisible = false;this.$refs.userForm.resetFields();},submitForm(formName) {this.$refs.userForm.validate((valid) => {if (valid) {this.centerDialogVisible = true;} else {console.log('error submit!!');return false;}});},resetForm(formName) {//this.$refs[formName].resetFields();this.$refs.userForm.resetFields();}}
}
</script><style scoped>
.container {display: flex;justify-content: center;align-items: center;height: 100vh; /* 设置父容器的高度为视口高度,使其充满整个屏幕 */
}.center-container {max-width: 600px; /* 设置内部容器的最大宽度,根据需求进行调整 */
}
</style>
动态列表表单
<template><div class="container"><div class="center-container"><el-form :model="{'contractData':contractData}" ref="contForm"><el-table :data="contractData" border style="width: 100%;" stripe><el-table-column label="序号" min-width="5%"><template slot-scope="scope"><p class="text-align:center;">{{ scope.$index + 1 }}</p></template></el-table-column><el-table-column prop="contName" label="合同名称" min-width="20%"><template slot-scope="scope"><el-form-item :prop="'contractData.'+scope.$index+'.contName'":rules="contRule.contName"><el-inputv-model.trim="scope.row.contName"placeholder="请输入合同名称" maxlength="200"></el-input></el-form-item></template></el-table-column><el-table-column label="合同编号" min-width="20%"><template slot-scope="scope"><el-form-item :prop="'contractData.'+scope.$index+'.contCode'":rules="contRule.contCode"><el-inputv-model.trim="scope.row.contCode" maxlength="200"placeholder="合同编号"></el-input></el-form-item></template></el-table-column></el-table><el-form-item><p><el-button @click="addCont()">添 加</el-button><el-button type="primary" @click="submitForm()">保 存</el-button><el-button @click="resetForm()">重 置</el-button></p></el-form-item></el-form></div><el-dialogtitle="提示":visible.sync="centerDialogVisible"width="30%"@close="closeDialog":close-on-click-modal="false":close-on-press-escape="false"center><span><pre>{{ contractData }}</pre></span><span slot="footer" class="dialog-footer"><el-button @click="centerDialogVisible = false">取 消</el-button><el-button type="primary" @click="centerDialogVisible = false">确 定</el-button></span></el-dialog></div>
</template><script>
export default {name: "validate-01",data() {return {contractData: [],contRule: {contCode: [{required: true,message: '合同编号不能为空',trigger: 'change'}],contAmt: [{required: true, message: '合同金额不能为空', trigger: 'change'},{pattern: /^(0\.0*[1-9]+[0-9]*$|[1-9]+[0-9]*\.[0-9]*[0-9]$|[1-9]+[0-9]*$)/,message: '非法数字'},{pattern: /^(([1-9]\d*)|\d)(\.\d{1,2})?$/,message: '最多两位小数'},],contName: [{required: true,message: '请输入合同名称',trigger: 'change'}],},centerDialogVisible: false,};},methods: {closeDialog() {this.centerDialogVisible = false;this.$refs.contForm.resetFields();},submitForm() {this.$refs.contForm.validate((valid) => {if (valid) {if (this.contractData.length === 0) {this.$message({showClose: true,message: '请先添加合同',type: 'warning',duration: 1500});} else {this.centerDialogVisible = true;}} else {console.log('error submit!!');return false;}});},resetForm() {//this.$refs[formName].resetFields();this.$refs.contForm.resetFields();},addCont() {this.contractData.push({contName: '',contCode: ''});}}
}
</script><style scoped></style>
文件校验
<template><div class="container"><div class="center-container"><el-form :model="userForm" :rules="rules" ref="userForm" label-width="100px"class="demo-userForm"><el-form-item label='附件' prop='fileList'><el-upload class='m-upload'action='/mock/user/img/upload':headers='headers'accept='.jpg,.png,.jpeg':on-success='handleAvatarSuccess':file-list='userForm.fileList':limit='2':on-exceed='handleExceed':on-preview='handlePreview':on-remove='handleRemove':before-upload="beforeAvatarUpload":before-remove="beforeRemove"><el-button type='primary'>上传</el-button></el-upload></el-form-item><el-form-item><el-button type="primary" @click="submitForm('userForm')">保 存</el-button><el-button @click="resetForm('userForm')">重 置</el-button></el-form-item></el-form></div><el-dialogtitle="提示":visible.sync="centerDialogVisible"width="30%"@close="closeDialog":close-on-click-modal="false":close-on-press-escape="false"center><span><pre>{{ userForm }}</pre></span><span slot="footer" class="dialog-footer"><el-button @click="centerDialogVisible = false">取 消</el-button><el-button type="primary" @click="centerDialogVisible = false">确 定</el-button></span></el-dialog></div>
</template><script>
import VueCookies from 'vue-cookies';export default {name: "validate-01",data() {return {userForm: {fileList: []},rules: {fileList: [{type: 'array', required: true, message: '请上传附件', trigger: ['change', 'blur']},{type: 'array', min: 2, message: '请至少上传2个附件', trigger: 'change'},],},centerDialogVisible: false,};},computed: {headers() {return {'Authorization': 'Bearer ' + VueCookies.get('access_token') // 直接从本地获取token就行};},},methods: {closeDialog() {this.centerDialogVisible = false;this.$refs.userForm.resetFields();},submitForm() {this.$refs.userForm.validate((valid) => {if (valid) {this.centerDialogVisible = true;} else {console.log('error submit!!');return false;}});},resetForm() {this.$refs.userForm.resetFields();},handleAvatarSuccess(response, file, fileList) {//上传成功console.log("response:", JSON.stringify(response))let self = this;let fileInfo = {...response.data};fileInfo.name = fileInfo.fileName;self.userForm.fileList.push(fileInfo);this.$refs.userForm.validateField("fileList")this.$forceUpdate();},handleExceed(files, fileList) {this.$message.warning('当前限制选择 2 个文件,本次选择了' + files.length + '个文件,共选择了' + (files.length + fileList.length) + ' 个文件');},handlePreview(val) {console.log("val:", JSON.stringify(val))},handleRemove() {this.userForm.fileList = [];},beforeAvatarUpload() {},beforeRemove() {}}
}
</script><style scoped>
.container {display: flex;justify-content: center;align-items: center;height: 100vh; /* 设置父容器的高度为视口高度,使其充满整个屏幕 */
}.center-container {max-width: 600px; /* 设置内部容器的最大宽度,根据需求进行调整 */
}
</style>
多表单el-form提交校验
使用Promise语法
<template><div class="container"><div class="center-container"><el-form :model="userForm1" :rules="rules" ref="userForm1" label-width="100px"class="demo-userForm"><span>基本信息1:</span><el-form-item label="姓名" prop="name"><el-input v-model="userForm1.name"></el-input></el-form-item></el-form><el-form :model="userForm2" :rules="rules" ref="userForm2" label-width="100px"class="demo-userForm"><span>基本信息2:</span><el-form-item label="姓名" prop="name"><el-input v-model="userForm2.name"></el-input></el-form-item></el-form><el-button type="primary" @click="submitForm()">保 存</el-button><el-button @click="resetForm()">重 置</el-button></div><el-dialogtitle="提示":visible.sync="centerDialogVisible"width="30%"@close="closeDialog":close-on-click-modal="false":close-on-press-escape="false"center><span><pre>{{ userForm1 }}</pre></span><span><pre>{{ userForm2 }}</pre></span><span slot="footer" class="dialog-footer"><el-button @click="centerDialogVisible = false">取 消</el-button><el-button type="primary" @click="centerDialogVisible = false">确 定</el-button></span></el-dialog></div>
</template><script>
export default {name: "validate-01",data() {return {userForm1: {},userForm2: {},rules: {name: [{required: true, message: '请输入姓名', trigger: ['blur', 'change']},{min: 2, max: 5, message: '长度在 2 到 5 个字符', trigger: 'blur'}],},centerDialogVisible: false,};},methods: {closeDialog() {this.centerDialogVisible = false;this.$refs.userForm1.resetFields();this.$refs.userForm2.resetFields();},submitForm() {const p1 = new Promise((resolve, reject) => {this.$refs['userForm1'].validate(valid => {if (valid) resolve()})})const p2 = new Promise((resolve, reject) => {this.$refs['userForm2'].validate(valid => {if (valid) resolve()})})Promise.all([p1, p2]).then(() => {console.log('submit')this.centerDialogVisible = true;})},resetForm() {this.$refs.userForm1.resetFields();this.$refs.userForm2.resetFields();}}
}
</script><style scoped>
.container {display: flex;justify-content: center;align-items: center;height: 100vh; /* 设置父容器的高度为视口高度,使其充满整个屏幕 */
}.center-container {max-width: 600px; /* 设置内部容器的最大宽度,根据需求进行调整 */
}
</style>