You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue3 + Vee Validate4:验证选中数组长度以阻止空表单提交

解决Vue3 + Vee Validate4中选中数组的提交验证问题

为啥之前的方法不生效

你之前用watch监听selected数组后调用validate,但这个验证是独立于表单体系的,Vee Validate的Form组件无法识别这个验证结果,所以哪怕数组为空,点击提交还是会触发onSubmit。

正确实现方式

要让selected的验证成为表单整体验证的一部分,需要把它注册为表单字段,通过Vee Validate的表单管理机制处理验证。以下是完整的修改方案:

修改后的代码

<template>
  <Form @submit="onSubmit">
    <!-- 其他已正常验证的字段 -->
    
    <!-- 选择项操作区域 -->
    <div class="selection-area">
      <h3>未选中列表</h3>
      <div v-for="item in unselected" :key="item.id">
        <button @click="moveToSelected(item)">选择 {{ item.title }}</button>
      </div>

      <h3>已选中列表</h3>
      <div v-for="item in selected" :key="item.id">
        <button @click="moveToUnselected(item)">取消选择 {{ item.title }}</button>
      </div>
    </div>

    <!-- 显示选中数组的验证错误 -->
    <p class="error">{{ errors['selected'] }}</p>

    <button type="submit">提交</button>
  </Form>
</template>

<script setup>
import { ref, watch } from 'vue';
import { Form, useForm, defineRule } from 'vee-validate';

// 注册自定义验证规则(如果已在其他文件注册可省略)
defineRule('arrayLength', (array) => {
  if (array.length < 1) {
    return '请至少选择1项';
  }
  return true;
});

const unselected = ref([
  { title: 'Bram janssen', id: 1, value: 1 },
  { title: 'Bert Bertsma', id: 2, value: 2 },
  { title: 'Kees Keesma', id: 3, value: 3 },
  { title: 'Jan Janssen', id: 4, value: 4 },
  { title: 'Pieter Pietersma', id: 5, value: 5 },
  { title: 'Lars Klaver', id: 6, value: 6 },
]);
const selected = ref([]);

// 初始化表单,将selected注册为表单字段并绑定验证规则
const { handleSubmit, errors, form } = useForm({
  initialValues: {
    selected: selected.value,
  },
  rules: {
    selected: 'arrayLength', // 应用自定义验证规则
  },
});

// 同步selected数组和表单字段的变化(深度监听数组内容)
watch(selected, (newSelected) => {
  form.setValue('selected', [...newSelected]);
}, { deep: true });

// 移动选中项的逻辑
const moveToSelected = (item) => {
  const idx = unselected.value.findIndex(i => i.id === item.id);
  if (idx !== -1) {
    unselected.value.splice(idx, 1);
    selected.value.push(item);
  }
};

const moveToUnselected = (item) => {
  const idx = selected.value.findIndex(i => i.id === item.id);
  if (idx !== -1) {
    selected.value.splice(idx, 1);
    unselected.value.push(item);
  }
};

// 提交函数:只有所有验证通过才会执行内部逻辑
const onSubmit = handleSubmit((formValues) => {
  console.log('表单提交成功,选中项:', formValues.selected);
  // 在这里编写你的表单提交逻辑
});
</script>

<style scoped>
.error {
  color: red;
}
</style>

关键要点

  • 表单字段绑定:通过useForm将selected注册为表单字段,让Vee Validate把它纳入整体验证流程。
  • 自动验证拦截:handleSubmit会在提交前自动验证所有字段,包括selected,如果数组为空(验证失败),会直接阻止提交逻辑执行,并返回错误信息。
  • 错误提示:通过errors对象可以获取selected字段的验证错误,用来给用户提示。

更简洁的写法(无需单独的selected ref)

如果你不想维护单独的selected ref,可以直接使用表单的values来管理选中项,省去同步步骤:

// 去掉单独的selected ref,直接用表单的values
const { handleSubmit, errors, values } = useForm({
  initialValues: {
    selected: [],
  },
  rules: {
    selected: 'arrayLength',
  },
});

// 移动逻辑改为操作values.selected
const moveToSelected = (item) => {
  const idx = unselected.value.findIndex(i => i.id === item.id);
  if (idx !== -1) {
    unselected.value.splice(idx, 1);
    values.selected.push(item);
  }
};

const moveToUnselected = (item) => {
  const idx = values.selected.findIndex(i => i.id === item.id);
  if (idx !== -1) {
    values.selected.splice(idx, 1);
    unselected.value.push(item);
  }
};

内容的提问来源于stack exchange,提问作者Bram Janssen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 22:25:24