赞
踩
在项目中,通常会有切换表单需求,然后会遇到切换后表单校验会被触发的问题
第一种方法,使用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>
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。