项目需求:动态循环表单,并实现动态表单校验
页面:
<u--form label-position="top" :model="tmForm" ref="tmForm" label-width="0px" :rules='rules'>
<div v-for="(element, index) in tmForm.tmList.filter((item) => item.delFlag !== 1)" :key="index"
class="form-item">
<div v-if="element.txTip == 'Input'">{{ element.tmTitle }}</div>
<u-form-item :required="element.pz.sfBt == '0'" :prop="`tmList[${index}].value`"
:label="`第${getFilteredIndex(index)}题`" v-if="element.txTip != 'Input'">
<div class="tm-title">{{ element.tmTitle }}</div>
<div class="tm-sm" v-if="element.tmSm">题目说明:{{ element.tmSm }}</div>
<div class="tm-sm" v-if="element.txTip == 'Textarea'">
题目规则:请填写『{{ element.pz.zfMin }} ~ {{ element.pz.zfMax }}』个字
</div>
<div class="tm-sm" v-if="element.txTip == 'InputNumber'">
题目规则:请填写『{{ element.pz.szMin }} ~ {{ element.pz.szMax }}』之间,小数点不超过{{
element.pz.szDeciPlace
}}位的数
</div>
<div class="tm-sm" v-if="element.txTip == 'CheckBox' || element.txTip == 'twCheckBox'">
题目规则:请选择『{{ element.pz.dxMin }} ~ {{ element.pz.dxMax }}』个选项
</div>
<div class="tm-sm" v-if="element.txTip == 'TimePicker'">
题目规则:请选择『{{ element.pz.rqMin }} ~ {{ element.pz.rqMax }}』之间的时间
</div>
<div class="tm-sm" v-if="element.txTip == 'Upload'">
题目规则:请上传『{{ element.pz.dxMin }} ~ {{ element.pz.dxMax }}』张图片
</div>
<component style="margin-top: 10upx;" :optionList="element.optionList" :options="element.pz"
v-model="element.value" :is="getWidget(element.txTip)"
@updateValue="(newValue) => updateValue(element, newValue)"></component>
</u-form-item>
</div>
</u--form>
直接给rules里面循环加上校验规则,注意页面prop的写法 :prop="`tmList[${index}].value`"
export default {
data() {
return {
tmForm: {
tmList: []
},
rules: {}
}
},
mounted() {
this.setRules()
},
methods: {
// 循环设置rules
setRules() {
this.tmForm.tmList.forEach((ele, index) => {
this.$set(this.rules, `tmList[${index}].value`, [
{
validator: this.validate(ele),
trigger: 'change'
}
])
}),
},
// 表单验证方法
validate(element) {
return (rule, value2, callback) => {
let value = element.value //value2是空的,我手动赋值了
if (element.pz.sfBt === '0' && (!value || value.length < 1)) {
callback(new Error("请输入"));
return;
}
if (element.txTip == "Textarea") {
if (value && value.length > element.pz.zfMin) {
callback(); // 通过验证
} else {
callback(new Error("文本长度不能小于10位"));
}
}
if (element.txTip == "InputNumber") {
const regex = new RegExp(`^-?\\d+(\\.\\d{0,${element.pz.szDeciPlace}}})*$`);
// 判断是否在指定范围内且满足小数点位数要求
if (value >= element.pz.szMin && value <= element.pz.szMax && regex.test(value)) {
callback(); // 通过验证
} else {
callback(
new Error(
`请输入『${element.pz.szMin} ~ ${element.pz.szMax}』之间,小数点不超过${element.pz.szDeciPlace}位的数`
)
); // 验证失败
}
}
if (element.txTip == "CheckBox" || element.txTip == "twCheckBox") {
if (value.length >= element.pz.dxMin && value.length <= element.pz.dxMax) {
console.log(1);
callback(); // 通过验证
} else {
callback(new Error(`请选择『${element.pz.dxMin} ~ ${element.pz.dxMax}』个选项`)); // 验证失败
console.log(2);
}
}
if (element.txTip == "Upload") {
const imageUrls = value.split(","); // 将图片 URL 字符串拆分为数组
if (imageUrls.length >= element.pz.dxMin) {
callback(); // 验证通过
} else {
callback(new Error(`请至少上传 ${element.pz.dxMin} 张图片`)); // 验证失败
}
}
if (element.txTip == "Address" && element.pz.sfXxdz == "0") {
if (value.value2) {
callback(); // 验证通过
} else {
callback(new Error(`请填写详细地址`)); // 验证失败
}
}
if (element.txTip == "PhoneNumber") {
const reg = /^1[3-9]\d{9}$/; // 定义手机号码的正则表达式
if (reg.test(value)) {
callback(); // 验证通过
} else {
callback(new Error("手机号码格式不正确")); // 验证失败
}
}
if (element.txTip == "IdNumber") {
const reg = /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/; // 定义身份证号码的正则表达式
if (reg.test(value)) {
callback(); // 验证通过
} else {
callback(new Error("身份证号码格式不正确")); // 验证失败
}
}
if (element.txTip == "Email") {
const reg = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/; // 定义邮箱地址的正则表达式
if (reg.test(value)) {
callback(); // 验证通过
} else {
callback(new Error("邮箱地址格式不正确")); // 验证失败
}
}
callback();
};
},
}
}