vue动态多级表单增删改查及校验

3,850 阅读4分钟

了解项目需求,构建基本html+ css

项目需求是: 可以添加很多标准,一条标准里有很多要点,对其进行输入,打分等功能,每条要点可以进行删除,每条大的标准可以进行删除,点击提交对每项进行校验,成品是下图:

寻找合适的element ui框架,学会高效复制粘贴~.~ 节约时间

element ui提供了动态增减表单项,但是只有一层,我们的数据需要进行多层级遍历渲染,不是很符合需求,所以需要自己写;分为创建和编辑,我们这里只说创建部分。 不论是一开始的添加、删除项目还是添加、删除要点都还不涉及后台接口联调,纯前端操作。下面是基本布局

<div>
    <div class="standradList">
        <span>评课标准:</span>
        <div class="productList" v-if="obj.EvaluationItemParamDTO.length!=0">
          <div class="list" v-for="(item,index) in obj.EvaluationItemParamDTO" :key="index">
            <el-form :ref="'objs'+index" :model="item" label-width="100px">
              <el-form-item
                label="评分项目:"
                prop="ItemName"
                :rules="{ required: true, message: '请输入评分项目', trigger: 'blur' }"
              >
                <el-input v-model="item.ItemName" maxlength="30"></el-input>
              </el-form-item>
              <div class="form_one" v-for="(items,ind) in item.EvaluationPointList" :key="ind">
                <el-form-item
                  label="评分要点:"
                  class="import_point"
                  :prop="'EvaluationPointList.'+ind+'.PointDetail'"
                  :rules="{ required: true, message: '请输入评分要点', trigger: 'blur' }"
                >
                  <el-input type="textarea" autosize v-model="items.PointDetail" maxlength="30"></el-input>
                </el-form-item>
                <el-form-item
                  label="分数:"
                  class="import_num"
                  label-width="60px"
                  :prop="'EvaluationPointList.'+ind+'.Score'"
                  :rules="{ required: true, message: '请输入分数', trigger: 'blur' }"
                >
                  <el-input
                    v-model="items.Score"
                    type="number"
                    oninput="if(value.length>4)value=value.slice(0,4)"
                  ></el-input>
                </el-form-item>
                <label style="color:#606266;font-size:14px;padding-left:6px">分</label>
                <el-button
                  class="del"
                  @click="deleteItems(index,ind)"
                  v-if="item.EvaluationPointList.length>1"
                  size="mini"
                  plain
                >删除</el-button>
              </div>
              <el-button
                size="mini"
                style="margin-left: 9.6%;color:#409EFF;border:1px solid #409EFF"
                @click="addItem('items',index,item.EvaluationPointList[item.EvaluationPointList.length-1].SortCode)"
                :disabled="item.EvaluationPointList.length>4"
              >+添加评分要点</el-button>
            </el-form>
            <span
              class="spanError"
              v-if="obj.EvaluationItemParamDTO.length>1"
              @click="deleteItem(index)"
            >×</span>
          </div>
        </div>
        <el-button
          style="width:200px;margin-left: 7%;color: #fff;background: #409EFF;"
          v-if="obj.EvaluationItemParamDTO.length<10"
          @click="addItem('item',obj.EvaluationItemParamDTO.length,obj.EvaluationItemParamDTO[obj.EvaluationItemParamDTO.length-1].SortCode)"
        >+添加评课项目</el-button>
      </div>
      <div class="validateForm" style="margin: 50px 0 50px 7%;text-align: right;padding-right: 1%;">
        <el-button @click="clearAll">取消</el-button>
        <el-button @click="submitStand" style="color: #fff;background: #409EFF;">提交</el-button>
      </div>
  </div>

虽然是动态创建,但是我们一开始提供了一个表单框,用于进行增删改查,下面是data初始化时绑定的变量及值:

data() {
    return {
      obj: {
        EvaluationTemplateEntity: {
          TotalScore: 100,
          TemplateName: "",
          CreateUserId: "",
          GradeId: "",
          SubjectId: ""
        },
        EvaluationItemParamDTO: [
          {
            ItemName: "",
            SortCode: 1,
            EvaluationPointList: [
              {
                PointDetail: "",
                Score: "",
                SortCode: "1"
              }
            ]
          }
        ]
      }
    };
}

我这里是和后台确认的数据格式(后面涉及到编辑时要渲染页面),所以数据格式最好统一,会方便很多

删除某个评分要点

deleteItems(index, ind) {
  //在这里我们需要根据传过来的值知道删的是哪个评分项目里的哪条评分要点
  this.obj.EvaluationItemParamDTO[index].EvaluationPointList.forEach(
    (item, indx) => {
      if (indx == ind) {
        this.obj.EvaluationItemParamDTO[index].EvaluationPointList.splice(
          ind,
          1
        );
      }
    }
  );
},

删除某条评分项目

deleteItem(index) {
  this.obj.EvaluationItemParamDTO.splice(index, 1);
},

添加评分要点或者添加评分项目(判断下是添加一个要点还是一个评分项目)

 addItem(str, ind, next) {
  if (str == "item") { //添加评分项目
    this.obj.EvaluationItemParamDTO.push({
      ItemName: "",
      SortCode: next + 1,
      EvaluationPointList: [
        {
          PointDetail: "",
          Score: "",
          SortCode: next + 1
        }
      ]
    });
  } else if (str == "items") {//添加评分要点
    //根据传值知道是那个评分项目里要添加评分要点
    this.obj.EvaluationItemParamDTO[ind].EvaluationPointList.push({
      PointDetail: "",
      Score: "",
      SortCode: next + 1
    });
  }
}

重点来了,表单校验!!!

简单的操作之后,要进行提交,对表单所有项进行校验。怎么对多次循环渲染的数据进行校验呢?下面的几步是关键,看截图:

标注1的地方是第一层循环和他的校验规则,对他进行校验需要的语法是  
:ref="'任意名'+index"  (一定要有:,因为是变量)

标注2的地方是第二层循环他的校验规则,对他进行校验需要的语法是
:prop="'循环的数组名. ' +index+ ' .校验当前项的字段名'"
(这里要注意!!! 循环的数组名后面一定要加 . , 校验当前项的字段名就是下面input中v-model绑定的值,前面一定要加 . 。)

如果前面循环书写不存在问题,下面就进行点击提交校验

submitStand() {
  //标红提示未填项
    let newArr = []; 
    let _self = this;
    this.obj.EvaluationItemParamDTO.forEach((item, index) => {
        checkForm("objs" + index); //这里的objs就是第一层循环要校验的那里(:ref='"objs"+index'),一定要写一样的
    });
    function checkForm(arrName) {
        var result = new Promise(function(resolve, reject) {
             _self.$refs[arrName][0].validate(valid => {
                if (valid) {
                    resolve();
                } else {
                    reject();
                }
            });
        });
        newArr.push(result);
    }
    Promise.all(newArr)
        .then(function() {
            setTimeout(function() {
                let sums = 0;
                _self.obj.EvaluationItemParamDTO.forEach((item, index) => {
                    item.EvaluationPointList.forEach((items, ind) => {
                        sums += Number(items.Score);
                    });
                })
                if(sums==100){
                    //这里是判断成功之后的事件
                }else{
                    //这里是判断失败的提示
                     _self.$message.error("总分有误,请重新设置")
                }
            }, 500);
        })
        .catch(function() { //捕捉异常
            _self.$message({
            message: "操作失败",
            type: "error"
            });
        });
}

至此多层级循环表单的校验就成功啦~.~, 如果还有疑问,请百度或者删了再敲一遍,因为我这里是没有问题的!一起努力哈!