vue3动态切换表单校验

在项目中,通常会有切换表单需求,然后会遇到切换后表单校验会被触发的问题

第一种方法,使用template包含el-form+v-if区分,缺点是el-form会被定义两次,表单model也会多次被定义及使用,后续维护会较难。

<template>
    <el-row style="margin-left: 20px">
		<el-radio-group v-model="type" @change="onChangeType">
			<el-radio :label="1">表单一</el-radio>
		    <el-radio :label="2">表单二</el-radio>
		</el-radio-group>
	</el-row>
	<template v-if="type === 1">
		<el-form :model="formOne"  :rules="rulesOne" ref="formOneRef" label-width="90px">
            ....
        </el-form>
	</template>
    <template v-else>
		<el-form :model="formTwo"  :rules="rulesTwo" ref="formTwoRef" label-width="90px">
            ....
        </el-form>
	</template>
</template>
<script setup>
import { ref, reactive, toRefs, getCurrentInstance } from "vue";
const { proxy } = getCurrentInstance();
const type = ref(1);
const data = reactive({
    formOne: {},
    formTwo: {},
    rulesOne: {},
    rulesTwo: {}
});
const { formOne, formTwo, rulesOne, rulesTwo } = toRefs(data);

function onChangeType() {
    // vue3 不推荐使用proxy代替this,另一种方法定义ref,使用ref.value.resetFields() 触发
    proxy.$refs['formOneRef'].resetFields();
    proxy.$refs['formTwoRef'].resetFields();
}
</script>

第二种方法,使用el-form包含template+v-if区分,推荐使用这种,减少代码冗余,并且也利于维护

<template>
    <el-row style="margin-left: 20px">
		<el-radio-group v-model="type" @change="onChangeType">
			<el-radio :label="1">表单一</el-radio>
		    <el-radio :label="2">表单二</el-radio>
		</el-radio-group>
	</el-row>
    <el-form :model="form"  :rules="{ 1: rulesOne, 2: rulesTwo }[type]" ref="formRef">
        <template v-if="type === 1">
            ...
        </template>
        <template v-else>
            ...
        </template>
    </el-form>
</template>
<script setup>
import { ref, reactive, toRefs, getCurrentInstance } from "vue";
const { proxy } = getCurrentInstance();
const type = ref(1);
const data = reactive({
    form: {},
    rulesOne: {},
    rulesTwo: {}
});
const { formOne, formTwo, rulesOne, rulesTwo } = toRefs(data);

function onChangeType() {
    // vue3 不推荐使用proxy代替this,另一种方法定义ref,使用ref.value.resetFields() 触发
    proxy.$refs['formRef'].resetFields();
}
</script>

 但是很抱歉,第二种方法依然会触发校验,因为vnode没有变,v-if执行后还是上一个vnode,所以需要添加key来区分,也就是

<el-form :key="type" :model="form"  :rules="{ 1: rulesOne, 2: rulesTwo }[type]" ref="formRef">
</el-form>

这样的话,就可以取消主动校验了。

 再补充两点

1、名称后台请求检验,需要注意的是,校验时要考虑是新增状态,还是编辑状态

const validateNameRepate = async (rule, value, callback) => {
  if (value) {
    await validNameUnique({ name: value })
      .then((res) => {
        if (res?.code === 200) {
          const { data = 0 } = res;
          if (data === 0) callback();
          if (data === 1) callback(new Error("名称已存在"));
        }
      })
      .catch((e) => {
        callback(new Error(e));
      });
  }
};

const data = reactive({
  rules: {
    name: [
      { required: true, message: "名称不能为空", trigger: ["blur", "change"] },
      {
        min: 2,
        max: 20,
        message: "名称长度必须介于 2 和 20 之间",
        trigger: ["blur", "change"],
      },
      {
        validator: validateNameRepate,
        trigger: "blur",
      },
    ],
  },
});

2、el-form-item使用v-if动态校验,需要使用el-form-item 的属性rules来单独定义校验,切换时校验才不会主动触发

<el-form-item v-if="type === '1'" label="测试" prop="test" :rules="[{ required: true, message: '不能为空', trigger: 'change' } ]">
    <el-select v-model="missSat" placeholder="请选择" multiple clearable collapse-tags collapse-tags-tooltip>
        <el-option v-for="item in list" :key="item.id" :label="item.name" :value="item.id" />
    </el-select>
</el-form-item>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值