一、普通校驗(yàn)
綁定ref:ref="editRef"
<el-form label-position="top" :model="value" ref="editRef">
<el-form-item class="detail__modify">
<el-input v-model="out.outType"></el-input
>
</el-form-item>
</el-form>
...
提交時校驗(yàn):editRef.value.validate()
const editRef = ref();
editRef.value.validate().then(async function () {
try {
await fetchDetail({...param})
}
...
如果需要取消校驗(yàn),比如取消表單編輯的時候,就需要重置表單校驗(yàn),否則可能會有校驗(yàn)信息提示。此時使用 editRef.value.resetFields();
function cancel(): void {
editRef.value.resetFields();
handleClear();
ctx.emit('close');
}
二、循環(huán)表單項(xiàng)的校驗(yàn)
請求到的數(shù)據(jù)在表單里循環(huán)展示,每條數(shù)據(jù)都需要一個表單項(xiàng)進(jìn)行展示,對每個循環(huán)出來的表單項(xiàng)分別進(jìn)行校驗(yàn)。
循環(huán)的數(shù)據(jù)為value.outStations, props中outStations是循環(huán)的數(shù)組,index是循環(huán)的index,后邊拼接的是需要校驗(yàn)對象的字段名也即 v-model="out.type" 中綁定的字段名。
<div v-for="(out, index) in value.outStations" :key="index">
<div class="platform">
<el-form-item
label="Off-app platforms"
:prop="`outStations.${index}.type`"
:rules="
[COOPERATION.BR_TeleKwai_Partner_BR, COOPERATION.IN_Family__Group].includes(
Number(value.agreementId)
)
? []
: [{ required: true, message: 'Required', trigger: 'blur' }]
"
>
<el-input v-model="out.outType"></el-input>
</el-form-item>
...
<el-form-item>..</el-form-item>
....
</div>
</div>
rules是校驗(yàn),可以為每個form-item單獨(dú)設(shè)置(如上代碼),也可以在setup中設(shè)置(如下述所示)。校驗(yàn)方式都是一樣的。
在setup中設(shè)置rules:
-
校驗(yàn)規(guī)則為靜態(tài)校驗(yàn)
script:
const dataRules = reactive({
outType: [{ required: true, message: 'Required', trigger: 'blur' }],
});
template:
<el-form-item
:prop="`outStations.${index}.type`"
:rules="dataRules.outType"
></el-form-item>
-
校驗(yàn)規(guī)則根據(jù)條件動態(tài)校驗(yàn)
比如根據(jù)循環(huán)出的值判斷是否校驗(yàn),可以使用函數(shù)返回校驗(yàn)規(guī)則:
script:
// 傳入當(dāng)前校驗(yàn)的字段(type)以及判斷條件(id )
const funcRules = function (type: string, id: any): any {
if (type === 'outType' || type === 'fansCont') {
return [
COOPERATION.BR_TeleKwai_Partner_BR,
COOPERATION.IN_Family__Group,
].includes(Number(id))
? []
: [{ required: true, message: 'Required', trigger: 'blur' }];
}
};
template:
<el-form-item
:prop="`outStations.${index}.type`"
:rules="funcRules('outType', value.agreementId)"
>
> <el-input v-model="out.outType"></el-input
></el-form-item>
<el-form-item
:prop="`outStations.${index}.fansCont`"
:rules="funcRules('fansCont', value.agreementId)"
>
> <el-input v-model="out.fansCount"></el-input
></el-form-item>
三、循環(huán)表單項(xiàng)添加了異步校驗(yàn)函數(shù),全部校驗(yàn)通過才能提交
循環(huán)表單項(xiàng)里,如果給每個form-item 添加其他異步的校驗(yàn)方法,提交之前需要判斷所填數(shù)據(jù)是否滿足條件,才能提交,可使用Promise.all 方法。
template:
<ks-form-item
:prop="`outStations.${index}.userId`"
rules="
[{ required: true, message: 'Required', trigger: 'change' }]
"
>
<ks-input
v-model="out.userId"
placeholder="ID"
@input="checkVerify(out)"
></ks-input>
</ks-form-item>
checkVerify異步校驗(yàn)失敗則捕獲異常,返回false作為判斷值。
這里使用了 @input方法,一開始想到的使用@change方法,但是校驗(yàn)結(jié)果blur之后才能觸發(fā),后又改用@keyup方法,但是復(fù)制過去的值不會觸發(fā)校驗(yàn)。最后才想到用 @input方法 ,可以輸入實(shí)時校驗(yàn)。
Script:
async function checkVerify(info: any): Promise<any> {
try {
await fetchOutstation(info);
} catch (e) {
message.error(e);
return false;
}
}
...
// 對提交的對象數(shù)組的每一項(xiàng)都執(zhí)行一次異步校驗(yàn)函數(shù),得到一個執(zhí)行結(jié)果為promise的數(shù)組
const promiseAllArr = addForm.agreementOutInfos.map((info: any) => {
return checkVerify(info);
});
// 使用Promise.all 得到函數(shù)執(zhí)行結(jié)果
const result = await Promise.all(promiseAllArr);
const invalid = result.some((d: any) => d === false);// 如果都校驗(yàn)通過,result數(shù)組里沒有false 值
這里每個form 如果:model 綁定的數(shù)據(jù)是相同的,但是校驗(yàn)的ref值不能相同,ref是獲取dom節(jié)點(diǎn),對每個form 需要唯一綁定。 表單項(xiàng)要么寫在一個form 里,要么分成幾個form之后綁定不同的ref。
-
Vue單文件組件中多個同名的ref屬性,this.$refs的取值及其使用注意事項(xiàng)
下面是綁定多個表單之后,需要每個都校驗(yàn)通過才能進(jìn)行下一步。 原理同上。
Promise.all([editRef1.value, editRef2.value, editRef3.value].map(item => item.validate())).then(async function () { ... }
四、循環(huán)表單中單個表單的獨(dú)立校驗(yàn)
根據(jù)請求到的數(shù)據(jù)循環(huán)創(chuàng)建表單,每個表單都應(yīng)該是獨(dú)立的,校驗(yàn)規(guī)則也是獨(dú)立的。
前面提到的表單普通校驗(yàn)中,通過定義 const editRef = ref(); 給表單form綁定ref="editRef"得到整個表單的校驗(yàn)對象以及校驗(yàn)相關(guān)的方法。 如果表單是循環(huán)出來的,則該ref也應(yīng)該是動態(tài)綁定的。
重新定義editRef ,使用數(shù)組保存每個表單的指向,數(shù)組項(xiàng)應(yīng)該為Ref類型,可掛載dom節(jié)點(diǎn)相關(guān)的方法。
const editRef = ref<Array<Ref>>([]);
...
// 請求到數(shù)據(jù)賦值給ruleForm.agreementInfos之后,遍歷該對象為 editRef 賦值:
ruleForm.agreementInfos.forEach((item: any, index: number) => {
editRef.value.push(ref(`editRef${index}`)); // editRef[0] = ref(`editRef0`)
});
循環(huán)表單template,每個form綁定ref為:ref="editRef[idx]"
<div
v-for="(value, idx) in ruleForm.agreementInfos"
:key="value.agreementId"
>
<ks-form label-position="top" :model="value" :ref="editRef[idx]">
<ks-form-item>
<ks-input v-model="value.memberName"></ks-input
>
</ks-form-item>
</ks-form>
<div>
提交時找到當(dāng)前表單,該表單獨(dú)立校驗(yàn)通過之后才能將表單數(shù)據(jù)提交到服務(wù)器。關(guān)鍵點(diǎn): editRef.value[idx].value.validate()
script:
async function SubmitAgreementInfo(agreementId: any): Promise<any> {
let idx = -1;
const currentData: any = ruleForm.agreementInfos?.forEach((item: any, index: number) => {
if (item.agreementId === agreementId) {
idx = index;
}
});
editRef.value[idx].value.validate().then(async function () {
await fetchSubmit({ param });
});
}