vue動態(tài)生成新表單并且添加驗證校驗規(guī)則方式
一、需求場景以及注意事項
需求場景
1.用戶輸入數(shù)值,點擊按鈕彈出對話框的同時,按照用戶輸入的數(shù)值進行表單的渲染。

2.點擊按鈕之后,渲染效果如下:

注意事項
首先聲明我這里使用的是ant-design,現(xiàn)在只要在網(wǎng)上一搜都是vue+element的動態(tài)生成以及數(shù)據(jù)綁定,所以就打算出一篇文章記錄一下。
下面先說與UI框架無關(guān)的注意事項,無論使用的是Element還是ant都要關(guān)注的點,在文末會說有關(guān)于ant生成表單的校驗規(guī)則。
以下幾點是重點內(nèi)容,建議細品。
- 1.在初始情況下,每一個表單項(比如說每一個input)的綁定數(shù)據(jù)都為空,也就是在data中無定義,但是整個表單的數(shù)據(jù)綁定為空數(shù)組。這個空數(shù)組就相當(dāng)于表單項數(shù)據(jù)綁定的載體。
- 2.在渲染表單,也就是渲染DOM元素之前,必須填充這個空數(shù)組,使數(shù)組中的值與表單項需要綁定的值一一對應(yīng)。除此之外,只要是在動態(tài)生成的內(nèi)容中中,需要綁定的數(shù)據(jù),都需要在渲染之前動態(tài)生成完畢。
- 3.在渲染表單之前,必須使用v-if判斷數(shù)組是否為空,為空則不渲染。
- 4.此處v-if不得使用v-show代替,因為v-show代表的是頁面元素存在,處于隱藏狀態(tài)。但是我們需要綁定的數(shù)據(jù)還沒生成好,最終會報一堆undefined。而v-if的本質(zhì)是操作DOM,控制其是否渲染,而v-show是操作樣式,控制其顯示隱藏。
二、代碼結(jié)構(gòu)
template中
此處會體現(xiàn)注意點三和四
1.我這里使用的Number函數(shù)是ant提供的,作用就是將用戶輸入的數(shù)值由字符串轉(zhuǎn)換成Number類型,注意轉(zhuǎn)換成Number類型是必須進行的,如果是字符串,遍歷出來的也只是字符串中的具體字符。
轉(zhuǎn)換成Number之后效果也就類似于:
for(let i = 0; i < arr.length; i++)
<!-- 監(jiān)測構(gòu)建信息對話框 -->
<a-modal
:title="monitorTitle"
:visible="monitorModalVisible"
@ok="monitorModalOk"
@cancel="monitorModalCancel"
okText="確定"
cancelText="取消"
:width=850>
<!-- 當(dāng)控制展開折疊的數(shù)組有值時再渲染:注意點三/四 -->
<div v-if="monitorExpand.length > 0">
<!-- 通過數(shù)值一循環(huán)生成監(jiān)測區(qū) -->
<div v-for="(item1,index1) in Number(addForm.add_monitor_number)" :key="index1">
<!-- 監(jiān)測區(qū)標題與展開折疊文字 -->
<div class="monitor">
<span class="monitor_title">監(jiān)測區(qū)-{{item1}}</span>
<!-- 控制監(jiān)測區(qū)折疊與展開的文字與圖標 -->
<div>
<span v-show="monitorExpand[index1].expanded" @click="monitorFormExpand(index1)" style="color:#4257B9;cursor: pointer;">
<a-icon type="up"/>
<span>折疊</span>
</span>
<span v-show="!monitorExpand[index1].expanded" @click="monitorFormExpand(index1)" style="color:#4257B9;cursor: pointer;">
<a-icon type="down"/>
<span>展開</span>
</span>
</div>
</div>
<!-- 監(jiān)測區(qū)表單,需要展開折疊的效果,所以需要變量來控制 -->
<div class="monitor_form" v-show="monitorExpand[index1].expanded">
<a-form-model ref="monitorFormRef" :model="monitorForm" :label-col="{span:6}" :wrapper-col="{ span: 17 }">
<a-row>
<a-col :span="12">
<a-form-model-item label="名稱:" :rules="{ required: true, message: '名稱不能為空', trigger: 'blur'}" :prop="'monitor_area.'+index1+'.monitor_name'">
<a-input v-model="monitorForm.monitor_area[index1].monitor_name" placeholder="請輸入監(jiān)測構(gòu)建信息" :disabled="modalDisabled"/>
</a-form-model-item>
</a-col>
<a-col :span="12">
<a-form-model-item label="位置:" :rules="{ required: true, message: '位置不能為空', trigger: 'blur'}" :prop="'monitor_area.'+index1+'.monitor_position'">
<a-input v-model="monitorForm.monitor_area[index1].monitor_position" placeholder="請輸入監(jiān)測構(gòu)建信息" :disabled="modalDisabled"/>
</a-form-model-item>
</a-col>
</a-row>
<a-form-model-item label="監(jiān)測點數(shù)值:" :label-col="{span:3}" :wrapper-col="{ span:21 }">
<!-- 通過數(shù)值二循環(huán)生成監(jiān)測點數(shù) -->
<a-col :span="4" v-for="(item2,index2) in Number(addForm.add_point_number)" :key="index2">
<a-form-model-item :style="{ marginRight:'5px'}" :rules="{ required: true, message: '數(shù)值不能為空', trigger: 'blur'}" :prop="'monitor_area.'+index1+'.points.'+index2">
<a-input v-model="monitorForm.monitor_area[index1].points[index2]" :placeholder="index2+1" :disabled="modalDisabled"/>
</a-form-model-item>
</a-col>
</a-form-model-item>
</a-form-model>
</div>
</div>
</div>
</a-modal>
data中

此處會體現(xiàn)注意點一

methods中的按鈕事件,也就是觸發(fā)渲染之前的事件
1.事件綁定

2.事件處理函數(shù)
此處體現(xiàn)注意點三:頁面DOM元素渲染之前必須生成該DOM元素需要綁定的相關(guān)數(shù)據(jù)。
此處的折疊展開也是相關(guān)數(shù)據(jù),也需要渲染之前生成好。
此處我的綁定數(shù)據(jù)是通過按鈕生成的,大家也可以根據(jù)自己的實際需求,以其他事件為介質(zhì)。
// 按鈕點擊事件
inputPointMessage(){
// 在添加時,只有輸入了測區(qū)數(shù)量以及監(jiān)測點數(shù),才能進行構(gòu)建信息的填寫
if(this.addTitle=='添加'){
if(this.addForm.add_monitor_number == ''){
return this.$message.warning('請先輸入測區(qū)數(shù)量')
}
if(this.addForm.add_point_number == '')
return this.$message.warning('請先輸入監(jiān)測點數(shù)')
}
// 生成控制折疊展開的數(shù)組和表單綁定對象,使用let聲明,避免出現(xiàn)意外的全局變量
for(let i = 0; i < this.addForm.add_monitor_number ;i++){
// 生成控制折疊展開的數(shù)組
this.monitorExpand.push({expanded:true});
// 生成表單綁定對象
this.monitorForm.monitor_area.push({
// 名稱
monitor_name :'',
// 位置
monitor_position :'',
// 保存監(jiān)測點數(shù)的數(shù)組
points :[]
})
}
// 打開對話框
this.monitorModalVisible = true
},
3.控制展開與折疊的事件處理函數(shù)
// 信息表單的展開折疊
monitorFormExpand(index){
this.monitorExpand[index].expanded = !this.monitorExpand[index].expanded
},三、ant-design中的校驗規(guī)則
a-form-model
1.在此標簽上不進行rules屬性的綁定,但是需要綁定model屬性 。

a-form-model-item
1.在此標簽上必須綁定prop屬性,外帶一張ant官網(wǎng)截圖說明。由于我們需要使用校驗規(guī)則,所以該屬性的綁定是必須的。

2.在此標簽上必須綁定rules屬性,用于定義校驗規(guī)則。

3.如果還看不懂可看官網(wǎng)有關(guān)于FormModel組件的最后一個演示示例。我就是根據(jù)這個將需求寫出來的。

四、在點擊對話框確定按鈕時獲取該表單對象,并得出打印結(jié)果

五、遇到的問題及優(yōu)化
數(shù)據(jù)提交前校驗
通過我之前的方式生成的表單是多個,那么vue實例中,一個monitorFormRef就對應(yīng)了多個,如下:

那么這個數(shù)組的每一項都會有一個validate方法,只能循環(huán)調(diào)用validate方法了:
// 監(jiān)測構(gòu)建信息對話框確定按鈕
monitorModalOk(){
// 在點擊對話框確定的時候,對表單進行校驗
console.log(this.$refs.monitorFormRef)
// 創(chuàng)建空數(shù)組,保存多個校驗結(jié)果
let valids = []
this.$refs.monitorFormRef.forEach((item)=>{
item.validate(valid => {
// 將校驗結(jié)果保存到數(shù)組中,當(dāng)前item對應(yīng)表單的校驗全部通過為true,否則為false
valids.push(valid)
});
});
console.log(valids,'valids')
// 遍歷校驗結(jié)果數(shù)組,只要一個為false,則返回false,否則返回true
let finalValid = valids.every((item)=>{
return item == true
});
console.log(finalValid,'finalValid')
// 當(dāng)全部表單的表單項沒有全部通過,直接返回
if(!finalValid) return
// 執(zhí)行拿到數(shù)據(jù)之后的業(yè)務(wù)代碼,業(yè)務(wù)代碼不進行演示
// 關(guān)閉當(dāng)前對話框
this.monitorModalVisible = false
},
優(yōu)化一:element-ui同樣適用
只有用戶輸入了前面提到的數(shù)值一和數(shù)值二(只能是正整數(shù),不包含零),再繼續(xù)向下進行,以及表單的渲染,之前是只拿了字符串非空進行校驗,之前的代碼已經(jīng)注釋掉,目前修改如下:
數(shù)值一和數(shù)值二的校驗規(guī)則一樣,只體現(xiàn)其一:
// 測區(qū)數(shù)量
add_monitor_number: [{required: true, message: '測區(qū)數(shù)量不能為空', trigger: 'blur' },
{type:'number',message:'僅支持輸入正整數(shù)(不包含0)', trigger: 'blur',transform(value){
if(value){
// 將輸入的值轉(zhuǎn)為數(shù)字
var val = Number(value)
if(/^[+]{0,1}(\d+)$/.test(val) && val != 0) return val
// 返回false即為校驗失敗
return false
}
}} ],
// 按鈕點擊事件
// 按鈕點擊事件
inputPointMessage(){
// 定義變量判斷用戶輸入了相應(yīng)的值才可以進行表單的渲染,都通過校驗時為true,否則為false
let tempValid = true;
// 對數(shù)值一和數(shù)值二兩個值的正確性進行校驗(只能是正整數(shù),不包含零),只有兩個值的校驗通過了才可以繼續(xù)對表單進行渲染
this.$refs.addFormRef.validateField(['add_monitor_number','add_point_number'],(error)=>{
// 當(dāng)error存在即校驗未全部通過,
if (error) tempValid = false;
})
console.log(tempValid)
// 校驗不通過直接返回
if(!tempValid) return;
// if(this.addTitle=='添加'){
// if(this.addForm.add_monitor_number == ''){
// return this.$message.warning('請先輸入測區(qū)數(shù)量')
// }
// if(this.addForm.add_point_number == ''){
// return this.$message.warning('請先輸入監(jiān)測點數(shù)')
// }
// }
// 生成控制折疊展開的數(shù)組和表單綁定對象,使用let聲明,避免出現(xiàn)意外的全局變量
for(let i = 0; i < this.addForm.add_monitor_number ;i++){
// 生成控制折疊展開的數(shù)組
this.monitorExpand.push({expanded:true});
// 生成表單綁定對象
this.monitorForm.monitor_area.push({
// 名稱
monitor_name :'',
// 位置
monitor_position :'',
// 保存監(jiān)測點數(shù)的數(shù)組
points :[]
})
}
// 打開對話框
this.monitorModalVisible = true
},
循環(huán)生成表單數(shù)據(jù)重復(fù),在點擊時生成,多次點擊就會多次生成,在生成前添加判斷即可
當(dāng)前表單綁定的數(shù)據(jù)有值時,不再生成表單綁定數(shù)據(jù)。
// 當(dāng)前表單沒有綁定數(shù)據(jù)時,生成表單對象
if(this.monitorForm.monitor_area.length == 0){
// 生成控制折疊展開的數(shù)組和表單綁定對象,使用let聲明,避免出現(xiàn)意外的全局變量
for(let i = 0; i < this.addForm.add_monitor_number ;i++){
// 生成控制折疊展開的數(shù)組
this.monitorExpand.push({expanded:true});
// 生成表單綁定對象
this.monitorForm.monitor_area.push({
// 名稱
actual_measure_region_name :'',
// 位置
actual_measure_region_position :'',
// 保存監(jiān)測點數(shù)的數(shù)組
actual_measure_region_value :[]
})
}
}
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
關(guān)于vue的語法規(guī)則檢測報錯問題的解決
在配置路有的時候,陸續(xù)出現(xiàn)了各種報錯其中最多的是一些寫法,例如空格,縮進,各種括號,這篇文章主要介紹了關(guān)于vue的語法規(guī)則檢測報錯問題的解決,非常具有實用價值,需要的朋友可以參考下2018-05-05
Vuejs 用$emit與$on來進行兄弟組件之間的數(shù)據(jù)傳輸通信
本篇文章主要介紹了Vuejs 用$emit 與 $on 來進行兄弟組件之間的數(shù)據(jù)傳輸示例,非常具有實用價值,需要的朋友可以參考下。2017-02-02

