Vue.js中使用Element UI实现动态表单项管理及验证

在Vue.js项目中,表单是与用户交互的重要部分,特别是在需要动态管理表单项的场景下,如何优雅地实现添加、删除、上移、下移及验证功能变得尤为重要。本文将详细介绍如何使用Element UI来实现一个包含动态表单项管理以及验证功能的表单。

效果图如下


image.png

一、项目背景

假设我们正在开发一个活动管理系统,其中一个功能是为活动添加多条路线信息,每条路线包含路线名称、可参加人数和路线详情。用户需要能够动态地添加、删除、调整路线顺序,并且需要对所有表单项进行验证。

二、实现步骤

  1. 项目初始化
    首先,确保你的Vue项目已经安装了Element UI。如果未安装,可以通过以下命令进行安装:

    npm install element-ui --save
    

    然后在main.js中引入Element UI:

    import Vue from 'vue'; 
    import ElementUI from 'element-ui'; 
    import 'element-ui/lib/theme-chalk/index.css'; 
    
    Vue.use(ElementUI);
    
  2. 模板结构
    在组件的template部分,使用Element UI的el-form、el-descriptions、el-row、el-col、el-form-item、el-input等组件来构建表单。特别地,使用v-for指令来动态渲染表单项,并使用slot插槽来添加“新增”按钮。

        <template> 
        <!-- 省略了部分代码,详细代码见文末 --> 
        </template>
    
  3. 数据定义

    在data函数中定义表单数据form和验证规则rules。form中包含activityTravelLines数组,用于存储路线信息。rules中定义了表单项的验证规则。

    data() {  
      return {  
        form: {  
          activityTravelLines: [  
            {  
              name: "",  
              limitNumber: "",  
              lineDetail: "",  
              rulesId: 0,  
            },  
          ],  
          //其他字段  
        },  
        arrayFieldRulesId: 0,  
        rules: {  
          //其他验证规则  
        },  
      };  
    },
    
  4. 初始化数据
    在created钩子中,调用initData方法初始化数据。如果有初始化数据(如通过接口获取),则遍历activityTravelLines数组,为每一项添加rulesId,并更新验证规则。

    created() {  
      this.initData();  
      this.updateRules(); // 更新验证规则  
    },  
    methods: {  
      initData() {  
        // 省略了部分代码,详细代码见文末  
      },  
      // 其他方法...  
    }
    
  5. 动态管理表单项
    提供addItem、removeItem、moveUp、moveDown方法来实现表单项的添加、删除、上移、下移功能。每次操作后,都需要调用updateRules方法来更新验证规则。

    methods: {  
      // 省略了部分代码,详细代码见文末  
      addItem() {  
        // 省略了部分代码,详细代码见文末  
      },  
      removeItem(index) {  
        // 省略了部分代码,详细代码见文末  
      },  
      moveUp(index) {  
        // 省略了部分代码,详细代码见文末  
      },  
      moveDown(index) {  
        // 省略了部分代码,详细代码见文末  
      },  
      // 其他方法...  
    }
    
  6. 表单验证
    在submit方法中,使用this.$refs.form.validate方法来验证表单。如果验证通过,则执行提交操作。

    methods: {  
      // 省略了部分代码,详细代码见文末  
      submit() {  
        this.$refs["form"].validate((valid) => {  
          if (valid) {  
            //你的提交代码  
            console.log(this.form, "提交form表单");  
          }  
        });  
      },  
    }
    
  7. 样式定义
    使用SCSS来定义表单的样式,确保表单项之间的间距和布局合理。

    <style lang="scss" scoped>  
    .btnCont {  
      display: flex;  
      justify-content: space-between;  
      align-items: center;  
      margin-bottom: 5px;  
      .titleIndexCont {  
        font-family: PingFang SC, PingFang SC;  
        font-weight: 400;  
        font-size: 20px;  
        color: #333333;  
      }  
    }  
    </style>
    

三、完整代码

<template>
  <div class="container">
    <el-form ref="form" :model="form" :rules="rules" label-width="120px">
      <el-descriptions title="路线信息" :column="2">
        <template slot="extra">
          <el-button type="primary" @click="addItem" size="mini"
            >新 增</el-button
          >
        </template>
      </el-descriptions>
      <div
        v-for="(item, index) in form.activityTravelLines"
        :key="item.rulesId"
      >
        <div class="btnCont">
          <div class="titleIndexCont">
            {{ "路线" + (index + 1) }}
          </div>
          <div>
            <el-button
              type="danger"
              icon="el-icon-delete"
              size="mini"
              @click="removeItem(index)"
            ></el-button>
            <el-button
              type="success"
              icon="el-icon-top"
              size="mini"
              @click="moveUp(index)"
            ></el-button>
            <el-button
              type="success"
              icon="el-icon-bottom"
              size="mini"
              @click="moveDown(index)"
            ></el-button>
          </div>
        </div>
        <el-row>
          <el-col :span="12">
            <el-form-item
              label="路线名称:"
              :prop="`activityTravelLines.${index}.name`"
            >
              <el-input v-model="item.name"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item
              label="可参加人数"
              :prop="`activityTravelLines.${index}.limitNumber`"
            >
              <el-input
                v-model="item.limitNumber"
                type="number"
                :min="0"
              ></el-input>
            </el-form-item>
          </el-col>
        </el-row>
        <el-form-item
          label="路线详情:"
          :prop="`activityTravelLines.${index}.lineDetail`"
        >
          <el-input
            v-model="item.lineDetail"
            type="textarea"
            placeholder="请输入内容"
            maxlength="300"
            :rows="5"
            show-word-limit
          ></el-input>
        </el-form-item>
      </div>
      <!-- 其他el-form-item -->
    </el-form>
    <div class="footer">
      <el-button type="primary" @click="submit">确 定</el-button>
    </div>
  </div>
</template>
<script>
export default {
  data() {
    return {
      form: {
        activityTravelLines: [
          {
            name: "",
            limitNumber: "",
            lineDetail: "",
            rulesId: 0,
          },
        ],
        //其他字段
      },
      arrayFieldRulesId: 0,
      rules: {
        //其他验证规则
      },
    };
  },
  created() {
    this.initData();
    this.updateRules(); // 更新验证规则
  },
  mounted() {},
  methods: {
    initData() {
      //如果有初始化数据,要遍历form.activityTravelLines,在每一项里面添加rulesId
      if (this.id) {
        //假设getTravelDetail是你的详情接口
        getTravelDetail(this.id).then((res) => {
          this.form = res?.data ?? {};
          this.form.activityTravelLines = res?.data?.activityTravelLines ?? [];
          this.form.activityTravelLines.map((item, index) => {
            item.rulesId = index;
          });
          this.arrayFieldRulesId = this.form.activityTravelLines.length - 1;
          this.updateRules(); // 更新验证规则
        });
      }
    },
    // 添加表单项
    addItem() {
      this.arrayFieldRulesId++;
      this.form.activityTravelLines.push({
        name: "",
        limitNumber: "",
        lineDetail: "",
        rulesId: this.arrayFieldRulesId,
      });
      this.updateRules(); // 更新验证规则
    },

    // 删除表单项
    removeItem(index) {
      if (this.form.activityTravelLines.length == 1) {
        this.$message({ message: "不能小于一条路线", type: "warning" });
        return;
      }
      this.form.activityTravelLines.splice(index, 1);
      this.updateRules(); // 更新验证规则
    },
    // 上移表单项
    moveUp(index) {
      if (index > 0) {
        const movedItem = this.form.activityTravelLines.splice(index, 1)[0];
        this.form.activityTravelLines.splice(index - 1, 0, movedItem);
        this.updateRules(); // 更新验证规则
      }
    },
    // 下移表单项
    moveDown(index) {
      if (index < this.form.activityTravelLines.length - 1) {
        const movedItem = this.form.activityTravelLines.splice(index, 1)[0];
        this.form.activityTravelLines.splice(index + 1, 0, movedItem);
        this.updateRules(); // 更新验证规则
      }
    },
    // 更新验证规则
    updateRules() {
      // 为每个表单项添加验证规则
      this.form.activityTravelLines.forEach((item, index) => {
        this.rules[`activityTravelLines.${index}.name`] = [
          { required: true, message: "路线名称不能为空", trigger: "blur" },
        ];
        this.rules[`activityTravelLines.${index}.limitNumber`] = [
          { required: true, message: "可参加人数不能为空", trigger: "blur" },
        ];
      });
    },
    submit() {
      this.$refs["form"].validate((valid) => {
        if (valid) {
          //你的提交代码
          console.log(this.form, "提交form表单");
        }
      });
    },
  },
};
</script>
<style lang="scss" scoped>
.btnCont {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 5px;
  .titleIndexCont {
    font-family: PingFang SC, PingFang SC;
    font-weight: 400;
    font-size: 20px;
    color: #333333;
  }
}
</style>

四、总结

本文详细介绍了如何在Vue.js项目中使用Element UI实现一个包含动态表单项管理以及验证功能的表单。通过动态渲染表单项、管理表单项的顺序、以及进行表单验证,我构建了一个灵活且功能强大的表单组件。希望这篇文章能帮助你在项目中更好地处理类似的需求。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容