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

Vue3表单提交前验证:如何仅在字段合法时提交数据

Vue3表单验证通过后才提交数据的解决方案

你的问题核心在于send函数调用validate后没有检查验证结果,直接执行了提交逻辑。只要在验证后判断错误数组是否为空,就能实现「只有所有字段验证通过才提交数据」的需求,具体修改如下:

关键修改点

  1. 让validate返回验证状态:在函数末尾返回errors.value.length === 0,以此标识是否所有字段都验证通过。
  2. 在send中判断验证结果:只有验证通过(或当前主题为support)时,才执行fetch提交操作。
  3. 修复fetch数据格式问题:原代码直接传递reactive对象作为body会导致格式错误,需要转为JSON字符串。

修改后的完整代码

Script部分

// <script setup>
import { ref, reactive } from 'vue';

const formData = reactive({
  name: '',
  phone: '',
  message: '',
  subject: 'general',
})

const subjects = [
  { value: 'general', label: 'Personal information' },
  { value: 'question', label: 'Ask your question' },
  { value: 'support', label: 'Support help' }
]

const errors = ref([]) 

const validate = () => {
  errors.value = []
  if (formData.phone == '') {
    errors.value.push({ message: 'Phone number is missing' })
  }else if(!/^\d+$/.test(formData.phone)){
    errors.value.push({message: 'Please enter a valid phone number'})
  }

  if (formData.name == '') {
    errors.value.push({ message: 'Name is missing' })
  } else if (formData.name.length < 3) {
    errors.value.push({ message: 'The name must not be less than three letters' })
  }
  
  // 返回验证是否通过的状态
  return errors.value.length === 0
}

const send = (e) => {
  // support主题单独处理,不验证字段
  if (formData.subject === 'support') {
    console.log('打开技术支持聊天')
    // 这里可以添加跳转聊天窗口等逻辑
    return
  }
  
  // 执行验证,获取结果
  const isValid = validate()
  if (!isValid) {
    // 验证不通过,直接返回,不提交数据
    return
  }

  console.log(formData)
  fetch('URL', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify(formData) // 转为JSON字符串,确保后端能正确解析
  })
}

Template部分(无需修改)

<template>
  <form @submit.prevent="send">
    <h1>Information</h1>

    <label for="alternativ">Your choice</label>
    <select id="alternativ" v-model="formData.subject">
      <option v-for="subject in subjects" :value="subject.value">{{ subject.label }}</option>
    </select>

    <div v-if="formData.subject !== 'support'">
      <label for="name">Name</label>
      <input id="name" v-model="formData.name">

      <label for="phone">Phone</label>
      <input id="phone" v-model="formData.phone" type="tel" maxlength="10">
      <p v-for="error in errors" class="error">{{ error.message }}</p>
      <textarea v-if="formData.subject === 'question'" id="message" v-model="formData.message"
        placeholder="Write your message..."></textarea>
      <button type="submit">Send</button>
    </div>

    <p v-if="formData.subject === 'support'">Technical support is performed by our expert in the chat. Click the support button and describe your case</p>
    <button v-if="formData.subject === 'support'" type="submit">Open support</button>
  </form>
</template>

CSS部分(无需修改)

* {
  box-sizing: border-box;
}

h1 {
  color: #000;
  text-align: center;
  font-size: 32px;
}

form {
  width: 300px;
  padding: 16px;
  border-radius: 10px;
  margin: 0 auto;
  background-color: antiquewhite;
  justify-content: center;
  align-items: center;
  text-align: center;
}

label {
  width: 72px;
  font-weight: bold;
  display: inline-block;
  color: #000;
  font-size: 12px;
}

#name,
#phone {
  width: 180px;
  padding: 3px 10px;
  border: 1px solid #f6f6f6;
  border-radius: 3px;
  background-color: #f6f6f6;
  margin: 8px 0;
  display: inline-block;
}

textarea {
  width: 100%;
  height: 100px;
  border: 1px solid #f6f6f6;
  border-radius: 3px;
  background-color: #f6f6f6;
  margin: 8px 0;
  resize: none;
  display: block;
}

button {
  width: 100%;
  padding: 8px 16px;
  margin-top: 32px;
  border: 1px solid #000;
  border-radius: 5px;
  display: block;
  color: #fff;
  background-color: blue;
}
.error {
  color: red;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 01:21:04