需求比較簡單就是驗證一個表單,但是表單的項目是一個數組,每一個輸入框都是v-for動態綁定的,其實和一個穩定的表單校驗大部分要注意的點是一樣的,只是一個問題prop的取值如何取比較複雜。
數據結構是這樣的,routeTable中有倆個數組結構的子對象,而倆個數組中的元素結構又是一樣的,而且業務邏輯也一樣,所以將這兩個數組分別傳遞給同一種子組件,並傳遞了key的句柄url-type。
routeTable = {
serviceUrl: [{
id: 1,
weight: 1,
url: 'http://'
}],
subscribeUrl: [{
id: 1,
weight: 1,
url: 'http://'
}]
}
調用子組件及向子組件傳值,
<el-divider content-position="left">
<el-checkbox :checked="true" :disabled="true">
<span style="color: #0c93ff">業務地址列表</span>
</el-checkbox>
</el-divider>
<centring-appkey-route-url
ref="service"
:route-table="centringForm.routeTable"
:modifiable="modifiable"
url-type="serviceUrl"
@delRouteUrl="delRouteUrl"/>
<el-divider content-position="left">
<el-checkbox :checked="true" :disabled="true">
<span style="color: #0c93ff">訂閱地址列表</span>
</el-checkbox>
</el-divider>
<centring-appkey-route-url
ref="subscribe"
:route-table="centringForm.routeTable"
:modifiable="modifiable"
url-type="subscribeUrl"
@delRouteUrl="delRouteUrl"/>
子組件代碼
<template>
<div>
<el-form ref="routeUrlForm" :model="routeTable" size="mini" inline label-width="60px">
<div v-for="(item, index) in routeTable[urlType+'']" :key="index">
<el-row>
<el-col :span="4">
<el-form-item label="id" required>
<el-input :disabled="true" v-model="item.id" size="mini" style="width: 50px;"/>
</el-form-item>
</el-col>
<el-col :span="10">
<el-form-item :prop="urlType + '.' +index + '.url'" :rules="routeUrlRules.url" label="url">
<el-input :disabled="!modifiable" v-model="item.url" size="mini" style="width: 260px;"/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="權重" required>
<el-input-number :disabled="!modifiable" v-model="item.weight" :min="1" size="mini" style="width: 80px;"/>
</el-form-item>
</el-col>
<el-col :span="4">
<el-button v-if="modifiable && routeTable.serviceUrl.length - 1 == index" type="primary" size="mini" @click="addUrl">添加</el-button>
<el-button v-if="modifiable && routeTable.serviceUrl.length > 1" size="mini" type="danger" @click="deleteUrl(index)">刪除</el-button>
</el-col>
</el-row>
</div>
</el-form>
</div>
</template>
<script>
export default {
name: 'CentringAppkeyRouteUrl',
// eslint-disable-next-line vue/require-prop-types
props: ['routeTable', 'urlType', 'modifiable'],
data() {
var checkUrl = (rule, value, callback) => {
console.log(value)
// eslint-disable-next-line eqeqeq
if (value != null && value != '') {
var partten = /(http|ftp|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?/
if (partten.test(value)) {
callback()
} else {
callback(new Error('請輸入正確的url'))
}
} else {
callback(new Error('請輸入url'))
}
}
return {
routeUrlRules: {
url: [{ validator: checkUrl, trigger: 'blur' }]
}
}
},
methods: {
// 刪除按鈕
deleteUrl(index) {
// eslint-disable-next-line eqeqeq
if (this.routeTable[this.urlType + ''][index].is_new == true) { // 是新加的,直接刪
this.routeTable[this.urlType + ''].splice(index, 1)
} else { // 是已編排過的,刪之前要判斷是不是最後一個
var cnt = 0
this.routeTable[this.urlType + ''].forEach(item => { // 統計原有url個數
// eslint-disable-next-line eqeqeq
if (item.is_new != true) {
cnt += 1
}
})
if (cnt <= 1) {
this.$message.error('最後一個不可刪除!') // 是最後一個,不做操作
} else {
this.$emit('delRouteUrl', { urlType: this.urlType, routeUrl: this.routeTable[urlType + ''][index] })
}
}
},
// 添加按鈕
addUrl() {
var nextId = 0
this.routeTable[this.urlType + ''].forEach(item => { // 找最大id
if (item.id >= nextId) {
nextId = Number(item.id) + 1
}
})
this.routeTable[this.urlType + ''].push({
id: nextId,
weight: 1,
url: 'http://',
is_new: true // 手動添加標記
})
},
validate() {
this.$refs.routeTable[this.urlType + ''].Form.validate((valid) => {
alert(valid)
})
}
}
}
</script>
<style scoped>
</style>
其中要注意的有:
1.rules相關數據與一般的校驗都一樣
2.el-form中的model必須是一個Object類型,所以傳遞了routeTable這個對象。不帶model參數整個表單都不會啓動校驗的。
3.最關鍵也是最複雜的prop的值定位,這個值是以model爲根找起,我要找url就必須先找到他所在的數組,然後是數組的下標,最後定位到url,每一層級使用"."分隔開,最終就成了如下所示的寫法。
:prop="urlType + '.' +index + '.url'"