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'"

 

 

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