element-UI框架下對v-for循環生成的表單項進行校驗

 需求比較簡單就是驗證一個表單,但是表單的項目是一個數組,每一個輸入框都是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'"

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章