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

基于Zod校验规则:根据contactNumber状态控制email字段必填性

实现邮箱与手机号的联动必填校验

根据需求,默认邮箱为必填项,当手机号字段有值时邮箱变为可选,清空手机号后邮箱恢复必填。以下是不同技术栈的实现方案:

原生JavaScript实现

通过监听手机号输入框的输入事件,动态修改邮箱的required属性,同时在表单提交时做二次校验避免绕过前端限制:

<form id="contactForm">
  <div>
    <label for="email">邮箱:</label>
    <input type="email" id="email" name="email" required>
  </div>
  <div>
    <label for="contactNumber">手机号:</label>
    <input type="tel" id="contactNumber" name="contactNumber">
  </div>
  <button type="submit">提交</button>
</form>

<script>
const contactNumberInput = document.getElementById('contactNumber');
const emailInput = document.getElementById('email');

// 实时监听手机号输入变化
contactNumberInput.addEventListener('input', () => {
  const hasContact = contactNumberInput.value.trim() !== '';
  emailInput.required = !hasContact;
  
  // 清除不必要的校验提示
  if (hasContact && emailInput.validity.valueMissing) {
    emailInput.setCustomValidity('');
  }
});

// 表单提交时的兜底校验
document.getElementById('contactForm').addEventListener('submit', (e) => {
  const hasContact = contactNumberInput.value.trim() !== '';
  if (!hasContact && emailInput.value.trim() === '') {
    e.preventDefault();
    emailInput.setCustomValidity('请填写邮箱');
    emailInput.reportValidity();
  } else {
    emailInput.setCustomValidity('');
  }
});
</script>

Vue 3 实现

利用响应式数据动态绑定邮箱的required属性,也可结合校验库实现更规范的校验逻辑:

基础版实现

<template>
  <form @submit.prevent="handleSubmit">
    <div>
      <label for="email">邮箱:</label>
      <input 
        v-model="form.email" 
        type="email" 
        id="email" 
        :required="!form.contactNumber.trim()"
      >
    </div>
    <div>
      <label for="contactNumber">手机号:</label>
      <input 
        v-model="form.contactNumber" 
        type="tel" 
        id="contactNumber"
      >
    </div>
    <button type="submit">提交</button>
  </form>
</template>

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

const form = reactive({
  email: '',
  contactNumber: ''
});

const handleSubmit = () => {
  // 手动兜底校验
  if (!form.contactNumber.trim() && !form.email.trim()) {
    alert('请填写邮箱');
    return;
  }
  // 执行表单提交逻辑
  console.log('提交数据:', form);
};
</script>

结合VeeValidate校验库实现

<template>
  <Form @submit="handleSubmit">
    <Field 
      name="email" 
      type="email" 
      :rules="{ required: !form.contactNumber.trim() }"
      label="邮箱"
    />
    <ErrorMessage name="email" class="error" />
    
    <Field 
      name="contactNumber" 
      type="tel" 
      v-model="form.contactNumber"
      label="手机号"
    />
    
    <button type="submit">提交</button>
  </Form>
</template>

<script setup>
import { Form, Field, ErrorMessage } from 'vee-validate';
import { reactive } from 'vue';

const form = reactive({
  contactNumber: ''
});

const handleSubmit = (values) => {
  console.log('提交数据:', values);
};
</script>

React 函数组件实现

通过useState跟踪手机号状态,动态设置邮箱的required属性:

import { useState } from 'react';

export default function ContactForm() {
  const [email, setEmail] = useState('');
  const [contactNumber, setContactNumber] = useState('');

  const handleSubmit = (e) => {
    e.preventDefault();
    // 兜底校验
    if (!contactNumber.trim() && !email.trim()) {
      alert('请填写邮箱');
      return;
    }
    // 执行提交逻辑
    console.log('提交数据:', { email, contactNumber });
  };

  return (
    <form onSubmit={handleSubmit}>
      <div>
        <label htmlFor="email">邮箱:</label>
        <input
          type="email"
          id="email"
          value={email}
          onChange={(e) => setEmail(e.target.value)}
          required={!contactNumber.trim()}
        />
      </div>
      <div>
        <label htmlFor="contactNumber">手机号:</label>
        <input
          type="tel"
          id="contactNumber"
          value={contactNumber}
          onChange={(e) => setContactNumber(e.target.value)}
        />
      </div>
      <button type="submit">提交</button>
    </form>
  );
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 09:10:18