Vue3表单提交前验证:如何仅在字段合法时提交数据
Vue3表单验证通过后才提交数据的解决方案
你的问题核心在于send函数调用validate后没有检查验证结果,直接执行了提交逻辑。只要在验证后判断错误数组是否为空,就能实现「只有所有字段验证通过才提交数据」的需求,具体修改如下:
关键修改点
- 让
validate返回验证状态:在函数末尾返回errors.value.length === 0,以此标识是否所有字段都验证通过。 - 在
send中判断验证结果:只有验证通过(或当前主题为support)时,才执行fetch提交操作。 - 修复
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
相关产品推荐
相关产品推荐

