IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> vue 做分步表单验证——动态组件、v-if -> 正文阅读

[JavaScript知识库]vue 做分步表单验证——动态组件、v-if

一、分步最后一步提交——v-if

将form表单写在一个页面,一张表,只切换里面的el-form-item

实现思路:

? ? ? ? 点击下一步:进行表格验证 检验通过下一步——想对应的active(步骤step的值)进行加加,因为这里只有三步 所以最后一步的时候 active直接为2 ,切按钮变为“提交”

? ? ? ? 点击提交:进行表单校验后 将数据传给后台 返回成功后 关闭弹层,表单数据初始化

? ? ? ? 点击上一步:相应步骤的值active减减,直到第一步,active=0

?在实现过程中遇到一下问题(表单验证时)

? ? ? ? 1、切换表单 部分验证失效 ——(第一步的input有验证,最后一步input 验证失效)

? ? ? ? ? ? ? ? 解决:将<template>标签切换改成<div>

? ? ? ? 2、提交表单后做数据初始化,弹层关闭——在打开弹层时,校验自动显示了,且验证第一个input对应了最后一个验证。

? ? ? ? 解决:因为一开始是使用 object.assign(this.$data,this.$options.data())进行初始化的,出现了以上问题,尝试在每个切换处加“key”后有点效果,但控制台会报“验证的一些错误。

????????最后使用object.assign(this.$data.form,this.$options.data().form)进行表单form初始化,this.active = 0 (步骤初始化),关闭弹层。就没问题了

?表单值初始化,我不想一个个那么赋值,才想着使用Object.assign()方法。不知道大佬们有没有更好的方法,求指导。

效果图

?

完整代码

<template>
  <el-dialog title="提示" :visible.sync="dialogVisible" width="50%">
    <el-steps :active="active" finish-status="success">
      <el-step title="If步骤 1"></el-step>
      <el-step title="If步骤 2"></el-step>
      <el-step title="If步骤 3"></el-step>
    </el-steps>
    <div>
      <el-form ref="ruleForm" :model="form" :rules="rules" label-width="100px">
        <div v-if="active === 0">
          <el-form-item label="密码" prop="pass">
            <el-input
              type="password"
              v-model="form.pass"
              autocomplete="off"
            ></el-input>
          </el-form-item>
          <el-form-item label="确认密码" prop="checkPass">
            <el-input
              type="password"
              v-model="form.checkPass"
              autocomplete="off"
            ></el-input>
          </el-form-item>
          <el-form-item label="年龄" prop="age">
            <el-input v-model.number="form.age"></el-input>
          </el-form-item>
          <el-form-item>
            <!-- <el-button type="primary" @click="submitForm('form')">提交</el-button>
    <el-button @click="resetForm('form')">重置</el-button> -->
          </el-form-item>
        </div>
        <div v-if="active === 1">
          <el-form-item label="活动名称" prop="name">
            <el-input v-model="form.name"></el-input>
          </el-form-item>
          <el-form-item label="活动区域" prop="regionActive">
            <el-select v-model="form.regionActive" placeholder="请选择活动区域">
              <el-option label="区域一" value="shanghai"></el-option>
              <el-option label="区域二" value="beijing"></el-option>
            </el-select>
          </el-form-item>
          <el-form-item label="活动时间">
            <el-col :span="11">
              <el-form-item prop="date1">
                <el-date-picker
                  type="date"
                  placeholder="选择日期"
                  v-model="form.date1"
                  style="width: 100%"
                ></el-date-picker>
              </el-form-item>
            </el-col>
            <el-col class="line" :span="2">-</el-col>
            <el-col :span="11">
              <el-form-item prop="date2">
                <el-time-picker
                  placeholder="选择时间"
                  v-model="form.date2"
                  style="width: 100%"
                ></el-time-picker>
              </el-form-item>
            </el-col>
          </el-form-item>
          <el-form-item label="即时配送" prop="delivery">
            <el-switch v-model="form.delivery"></el-switch>
          </el-form-item>
          <el-form-item label="活动性质" prop="type">
            <el-checkbox-group v-model="form.type">
              <el-checkbox label="美食/餐厅线上活动" name="type"></el-checkbox>
              <el-checkbox label="地推活动" name="type"></el-checkbox>
              <el-checkbox label="线下主题活动" name="type"></el-checkbox>
              <el-checkbox label="单纯品牌曝光" name="type"></el-checkbox>
            </el-checkbox-group>
          </el-form-item>
          <el-form-item label="特殊资源" prop="resource">
            <el-radio-group v-model="form.resource">
              <el-radio label="线上品牌商赞助"></el-radio>
              <el-radio label="线下场地免费"></el-radio>
            </el-radio-group>
          </el-form-item>
          <el-form-item label="活动形式" prop="desc">
            <el-input type="textarea" v-model="form.desc"></el-input>
          </el-form-item>
        </div>
        <div v-if="active === 2">
          <el-form-item label="审批人" prop="users">
            <el-input v-model="form.users" placeholder="审批人"></el-input>
          </el-form-item>
          <el-form-item label="活动区域">
            <el-select v-model="form.region" placeholder="活动区域">
              <el-option label="区域一" value="shanghai"></el-option>
              <el-option label="区域二" value="beijing"></el-option>
            </el-select>
          </el-form-item>
          <el-form-item>
            <!-- <el-button type="primary" @click="onSubmit">查询</el-button> -->
          </el-form-item>
        </div>
      </el-form>
    </div>
    <div slot="footer">
      <el-button v-if="active === 2" @click="submit">提交</el-button>
      <el-button v-else @click="next">保存并下一步</el-button>
      <el-button @click="pre">上一步</el-button>
    </div>
  </el-dialog>
</template>

<script>
export default {
  data() {
    return {
      dialogVisible: false,
      active: 0,
      form: {
        users: "",
        region: "",
        name: "",
        regionActive: "",
        date1: "",
        date2: "",
        delivery: false,
        type: [],
        resource: "",
        desc: "",
        pass: "",
        checkPass: "",
        age: "",
      },
      rules: {
        pass: [{ required: true, message: "密码不能为空", trigger: "blur" }],
        desc: [
          { required: true, message: "活动形式不能为空", trigger: "blur" },
        ],
        users: [{ required: true, message: "shenp", trigger: "blur" }],
        type: [
          {
            type: "array",
            required: true,
            message: "请至少选择一个活动性质",
            trigger: "change",
          },
        ],
        resource: [
          { required: true, message: "请选择活动资源", trigger: "change" },
        ],
      },
    };
  },
  methods: {
    showDailog() {
      this.dialogVisible = true;
    },
    async submit() {
      let that = this;
      try {
        const check = await this.$refs["ruleForm"].validate();
        console.log(check, "检验布尔");
        setTimeout(() => {
          this.$message.success("提交表格成功");
          //  that.$refs["ruleForm"].clearValidate();
          // this.dialogVisible = false;
          //     let obj =  {
          //   users: "",
          //   region: "",
          //   name: "",
          //   regionActive: "",
          //   date1: "",
          //   date2: "",
          //   delivery: false,
          //   type: [],
          //   resource: "",
          //   desc: "",
          //   pass: "",
          //   checkPass: "",
          //   age: "",
          // }
          // this.form = obj
          this.active = 0;
          this.dialogVisible = false;
          Object.assign(that.$data.form, that.$options.data().form); // 单个form 初始
          // Object.assign(that.$data, that.$options.data()) 所以数据初始,使用这个 再打开弹层时验证显示会有问题 加key缓解
        }, 500);
      } catch (error) {
        console.log(error, "校验");
      }
      console.log(this.form, "form提交");
    },
    async next() {
      try {
        const check = await this.$refs["ruleForm"].validate();
        console.log(check, "检验布尔");
        if (this.active++ === 2) this.active = 2;
      } catch (error) {
        console.log(error, "校验");
      }

      console.log(this.form, "this.form下一步");
      // 进行表格校验成功后再到下一步
    },
    pre() {
      if (this.active-- === 0) this.active = 0;
      console.log(this.form, "this.form上一步");
    },
  },
};

</script>

<style>
</style>

二、组件切换 做 步骤

?小说明——原先就是使用的component 组件切换做分步,最后一步进行提交,然后慢慢搞复杂了

这里就简单记记我当初用component的心路

思路:

1、定义三个组价 form1、form2、form3? 和一个组件切换页formdailog.vue。在formdailog页面使用<componet is="组件名”/> 进行切换,定义表单的所有属性allForm 传值进组件

?

?这里的一些方法逻辑都在各自组件里,通过ref来调用方法

?这里直接上代码了

formdailog.vue

<template>
  <el-dialog title="提示" :visible.sync="dialogVisible" width="30%">
    <div v-loading="loading" element-loading-text="提交中">
      <el-steps :active="active" finish-status="success">
        <el-step title="步骤 1"></el-step>
        <el-step title="步骤 2"></el-step>
        <el-step title="步骤 3"></el-step>
      </el-steps>
      <div class="form">
        <!-- <formOne v-if="active==0"/>
    <formTwo v-if="active==1"/>
    <formThree v-if="active==2"/> -->
        <keep-alive>
          <component
            :is="flag"
            ref="componetRef"
            :formInline="allForm"
            :form="allForm"
            :ruleForm="allForm"
          ></component>
        </keep-alive>
      </div>
      <el-button
        type=""
        v-if="this.flag === 'formThree'"
        style="margin-top: 12px"
        @click="submit"
        >提交</el-button
      >
      <el-button v-else style="margin-top: 12px" @click="next"
        >保存并下一步</el-button
      >

      <el-button style="margin-top: 12px" @click="last">上一步</el-button>

      <span slot="footer" class="dialog-footer">
        <el-button @click="dialogVisible = false">取 消</el-button>
        <el-button type="primary" @click="dialogVisible = false"
          >确 定</el-button
        >
      </span>
    </div>
  </el-dialog>
</template>

<script>
import formOne from "./form/form1.vue";
import formTwo from "./form/form2.vue";
import formThree from "./form/form3.vue";
export default {
  components: {
    formOne,
    formTwo,
    formThree,
  },
  data() {
    return {
      dialogVisible: false,
      active: 0,
      loading: false,
      flag: "formOne",
      allForm: {
        user: "",
        region: "",
        name: "",
        regionActive: "",
        date1: "",
        date2: "",
        delivery: false,
        type: [],
        resource: "",
        desc: "",
        pass: "",
        checkPass: "",
        age: "",
      },
    };
  },
  methods: {
    showDailog() {
      this.dialogVisible = true;
    },


    async next() {
      const check = await this.$refs["componetRef"].submitForm("ruleForm");
      if (!check) {
        return;
      }

      if (this.active++ >= 2) this.active = 2;
      switch (this.active) {
        case 0:
          this.flag = "formOne";
          
          break;
        case 1:
          this.flag = "formTwo";
          break;
        case 2:
          this.flag = "formThree";
          break;
      }

     
    },
    last() {
      this.active--;
      switch (this.active) {
        case 0:
          this.flag = "formOne";
          break;
        case 1:
          this.flag = "formTwo";
          break;
        case 2:
          this.flag = "formThree";
          break;
      }
    },
    //提交按钮—— 最后提交也掉子组件方法验证
    async submit() {
        let that = this

      const check = await this.$refs["componetRef"].submitForm("ruleForm");
      if (!check) {
        return;
      }

      try {
        await this.$confirm("是否提交表单, 是否继续?", "提示", {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          type: "warning",
        });
        this.active = 3;

        this.loading = true;
        setTimeout(() => {
          this.loading = false;
          this.$message.success("提交表单成功");
          this.dialogVisible = false;
           Object.assign(this.$data, this.$options.data())
        
           this.active = 0
        }, 3000);
      } catch (error) {
        this.active = 2;
        this.$message.error("取消提交");
      }
    },
  },
};
</script>

<style>
</style>

form1.vue

<template>
  <div class="form3">
    <el-form
      :model="ruleForm"
      status-icon
      :rules="rules"
      ref="ruleForm"
      label-width="100px"
      class="demo-ruleForm"
    >
      <el-form-item label="密码" prop="pass">
        <el-input
          type="password"
          v-model="ruleForm.pass"
          autocomplete="off"
        ></el-input>
      </el-form-item>
      <el-form-item label="确认密码" prop="checkPass">
        <el-input
          type="password"
          v-model="ruleForm.checkPass"
          autocomplete="off"
        ></el-input>
      </el-form-item>
      <el-form-item label="年龄" prop="age">
        <el-input v-model.number="ruleForm.age"></el-input>
      </el-form-item>
      <el-form-item>
        <!-- <el-button type="primary" @click="submitForm('ruleForm')">提交</el-button>
    <el-button @click="resetForm('ruleForm')">重置</el-button> -->
      </el-form-item>
    </el-form>
  </div>
</template>

<script>
export default {
  props: {
    ruleForm: {
      type: Object,
      default: {
        pass: "",
        checkPass: "",
        age: "",
      },
    },
  },
  data() {
    var checkAge = (rule, value, callback) => {
      if (!value) {
        return callback(new Error("年龄不能为空"));
      }
      setTimeout(() => {
        if (!Number.isInteger(value)) {
          callback(new Error("请输入数字值"));
        } else {
          if (value < 18) {
            callback(new Error("必须年满18岁"));
          } else {
            callback();
          }
        }
      }, 1000);
    };
    var validatePass = (rule, value, callback) => {
      if (value === "") {
        callback(new Error("请输入密码"));
      } else {
        if (this.ruleForm.checkPass !== "") {
          this.$refs.ruleForm.validateField("checkPass");
        }
        callback();
      }
    };
    var validatePass2 = (rule, value, callback) => {
      if (value === "") {
        callback(new Error("请再次输入密码"));
      } else if (value !== this.ruleForm.pass) {
        callback(new Error("两次输入密码不一致!"));
      } else {
        callback();
      }
    };
    return {
      // ruleForm: {
      //   pass: '',
      //   checkPass: '',
      //   age: ''
      // },
      rules: {
        pass: [{ validator: validatePass, trigger: "blur" }],
        checkPass: [{ validator: validatePass2, trigger: "blur" }],
        age: [{ validator: checkAge, trigger: "blur" }],
      },
    };
  },
  methods: {
    async submitForm(formName) {
      try {
        const flag = await this.$refs[formName].validate();
        return true;
      } catch (error) {
        this.$message.error("请填写表单信息");
        return false;
      }
    },
    resetForm(formName) {
      this.$refs[formName].resetFields();
    },
    // 清除
    clearValidate() {
      this.$refs["ruleForm"].clearValidate();
    },
  },
  deactivated() {
    this.$emit("DeactiveOneData", this.ruleForm);
  },
  activated() {
    this.clearValidate();
  },
};
</script>

<style>
</style>

form2.vue

<template>
  <div class="form2" key="form2">
    <el-form
      :model="form"
      :rules="rules"
      ref="ruleForm"
      label-width="100px"
      class="demo-form"
    >
      <el-form-item label="活动名称" prop="name">
        <el-input v-model="form.name"></el-input>
      </el-form-item>
      <el-form-item label="活动区域" prop="regionActive" >
        <el-select v-model="form.regionActive" placeholder="请选择活动区域" >
          <el-option label="区域一" value="shanghai"></el-option>
          <el-option label="区域二" value="beijing"></el-option>
        </el-select>
      </el-form-item>
      <el-form-item label="活动时间" required>
        <el-col :span="11">
          <el-form-item prop="date1">
            <el-date-picker
              type="date"
              placeholder="选择日期"
              v-model="form.date1"
              style="width: 100%"
            ></el-date-picker>
          </el-form-item>
        </el-col>
        <el-col class="line" :span="2">-</el-col>
        <el-col :span="11">
          <el-form-item prop="date2">
            <el-time-picker
              placeholder="选择时间"
              v-model="form.date2"
              style="width: 100%"
            ></el-time-picker>
          </el-form-item>
        </el-col>
      </el-form-item>
      <el-form-item label="即时配送" prop="delivery">
        <el-switch v-model="form.delivery"></el-switch>
      </el-form-item>
      <el-form-item label="活动性质" prop="type">
        <el-checkbox-group v-model="form.type">
          <el-checkbox label="美食/餐厅线上活动" name="type"></el-checkbox>
          <el-checkbox label="地推活动" name="type"></el-checkbox>
          <el-checkbox label="线下主题活动" name="type"></el-checkbox>
          <el-checkbox label="单纯品牌曝光" name="type"></el-checkbox>
        </el-checkbox-group>
      </el-form-item>
      <el-form-item label="特殊资源" prop="resource">
        <el-radio-group v-model="form.resource">
          <el-radio label="线上品牌商赞助"></el-radio>
          <el-radio label="线下场地免费"></el-radio>
        </el-radio-group>
      </el-form-item>
      <el-form-item label="活动形式" prop="desc">
        <el-input type="textarea" v-model="form.desc"></el-input>
      </el-form-item>
    </el-form>
  </div>
</template>

<script>
export default {
  props: {
    form: {
      type: Object,
      default: {
        name: "",
        regionActive: "",
        date1: "",
        date2: "",
        delivery: false,
        type: [],
        resource: "",
        desc: "",
      },
    },
  },
  data() {
    return {
      //   form: {
      //     name: "",
      //     regionActive: "",
      //     date1: "",
      //     date2: "",
      //     delivery: false,
      //     type: [],
      //     resource: "",
      //     desc: "",
      //   },
      rules: {
        name: [
          { required: true, message: "请输入活动名称", trigger: "blur" },
          { min: 3, max: 5, message: "长度在 3 到 5 个字符", trigger: "blur" },
        ],
        regionActive: [
          { required: true, message: "请选择活动区域", trigger: "change" },
        ],
        date1: [
          {
            type: "date",
            required: true,
            message: "请选择日期",
            trigger: "change",
          },
        ],
        date2: [
          {
            type: "date",
            required: true,
            message: "请选择时间",
            trigger: "change",
          },
        ],
        type: [
          {
            type: "array",
            required: true,
            message: "请至少选择一个活动性质",
            trigger: "change",
          },
        ],
        resource: [
          { required: true, message: "请选择活动资源", trigger: "change" },
        ],
        desc: [{ required: true, message: "请填写活动形式", trigger: "blur" }],
      },
    };
  },
  activated() {
    this.clearValidate()
  },
  mounted() {
    this.clearValidate()
  },
  methods: {
    // 提交验证
    async submitForm(formName) {
      try {
        const flag = await this.$refs[formName].validate();
        return true;
      } catch (error) {
        this.$message.error("请填写表单信息");
        return false;
      }
    },
    // 清除
    clearValidate() {
        this.$refs['ruleForm'].clearValidate();
    }
  },
  deactivated() {
    this.$emit("DeactiveOneData", this.form);
  },
};
</script>

<style>
</style>

form3.vue

<template>
  <div class="form1">
    <el-form ref="ruleForm" :rules="rules" :inline="true" :model="formInline" class="demo-form-inline">
      <el-form-item label="审批人" prop="user">
        <el-input v-model="formInline.user" placeholder="审批人"></el-input>
      </el-form-item>
      <el-form-item label="活动区域" key="form3">
        <el-select v-model="formInline.region" placeholder="活动区域" >
          <el-option label="区域一" value="shanghai"></el-option>
          <el-option label="区域二" value="beijing"></el-option>
        </el-select>
      </el-form-item>
      <el-form-item>
        <!-- <el-button type="primary" @click="onSubmit">查询</el-button> -->
      </el-form-item>
    </el-form>
  </div>
</template>

<script>
export default {
  props: {
    formInline: {
      type: Object,
      default: {
        user: "",
        region: "",
      },
    },
  },
  data() {
    return {
      //   formInline: {
      //     user: "",
      //     region: "",
      //   },
      rules:{
        user:  [ { required: true, message: "请输入审批人", trigger: "blur" }],
      }
    };
  },
  mounted() {
   
    this.clearValidate()
  },
    activated() {

    this.clearValidate()
  },
  methods: {
    async submitForm(formName) {
      try {
        const flag = await this.$refs[formName].validate();
        return true;
      } catch (error) {
        this.$message.error("请填写表单信息");
        return false;
      }
    },
           // 清除
    clearValidate() {
        this.$refs['ruleForm'].clearValidate();
    }
  },
};
</script>

<style>
</style>

这里最终效果跟1一样,只不过这是每个组件里面有方法

总结:每一步一提交适合组件切换,简单的最后一块提交的使用一个页面form用v-if(公共部分也可抽出封装)

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2022-10-08 20:32:10  更:2022-10-08 20:33:51 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/17 17:39:02-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码