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

Vanilla JS年龄验证模态框:正确输入后无法关闭问题求助

年龄验证模态框无法正常关闭的问题

我用Vanilla JS开发年龄验证模态框,目前能检测到未满18岁的情况并显示「Invalid Credentials」错误,但输入正确年龄后无法关闭模态框,求带解释的解决方案。


我的JS代码

const modal = document.getElementById("myModal");
const form = document.querySelector('form');
const loading = document.getElementById("loading");
const btnSubmit = document.getElementById('btnSubmit');

// 点击模态框外部关闭
window.onclick = function(event) {
  if (event.target == modal) {
    modal.style.display = "none";
  }
};

// 输入验证函数
function onlyNumbers(e) {
  const ageGate = document.querySelectorAll('.ageGate');
  const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
  const errMsgDiv = document.getElementById('errorMsg');

  let containsNumber = false
  ageGate.forEach(input => {
    if(numbers.some(num => input.value.includes(num))) containsNumber = true;
  })
  if (containsNumber || ageGate.value !== numbers && ageGate.value == '' || ageGate[2].value < 2004) {
    let paragraph = document.createElement('p');
    paragraph.innerHTML = 'Invalid Credentials';
    errMsgDiv.append(paragraph);
    e.preventDefault()
    }  else if (containsNumber = true) {
        btnSubmit.remove()
        loading.classList.remove('hide')
    }
    
};

模态框HTML代码

<div id="modal">
    <div class="modal-content">
        <div class="flex-container">
            <div>
                <img
                    src="{% static 'imgs/Fireball_logo.png' %}"
                    class="logo"
                    alt="fireball logo"
                />
                <h1>WOAH THERE!</h1>
                <p class="info-text">We just need to see something</p>
            </div>
            <form action="">
                {% csrf_token %}
                <div class="form-flex">
                    <input
                        class="ageGate"
                        type="text"
                        max-length="2"
                        placeholder="DD"
                    />
                    <input
                        class="ageGate"
                        type="text"
                        max-length="2"
                        placeholder="MM"
                    />
                    <input
                        class="ageGate"
                        type="text"
                        max-length="4"
                        placeholder="YYYY"
                    />
                </div>
                <p class="cookie-policy">
                    <small>
                        This site uses cookies. Cookie Policy. I agree
                        to the terms of use, and the privacy policy.
                        This information will not be used for marketing
                        purposes
                    </small>
                </p>
                <div class="text-center">
                    <button id="btnSubmit" class="btn" type="submit">
                        <p class="btn-text">Enter</p>
                    </button>
                    <img 
                        src="{% static 'imgs/spinner.gif' %}"
                        alt="spinner" 
                        id="loading" 
                        class="loading close">
                </div>
                <span id="errorMsg"></span>
            </form>
            <div>
                <img
                    src="{% static 'imgs/Drinkaware_logo.png' %}"
                    alt="Drinkaware Logo"
                />
            </div>
        </div>
    </div>
</div>

问题分析与修复方案

1. 核心问题梳理

你的代码存在3个关键问题导致验证通过后无法关闭模态框:

  • 模态框ID不匹配:HTML里模态框ID是modal,JS里写的是myModal,根本获取不到目标元素
  • 验证逻辑混乱:containsNumber = true是赋值而非比较操作,且年龄仅判断年份<2004,未考虑月日(比如2004年12月出生的用户可能还未满18)
  • 未添加验证通过后的关闭逻辑:没有在合法年龄分支里写关闭模态框的代码

2. 修复后的完整JS代码

const modal = document.getElementById("modal"); // 修正ID匹配问题
const form = document.querySelector('form');
const loading = document.getElementById("loading");
const btnSubmit = document.getElementById('btnSubmit');
const errMsgDiv = document.getElementById('errorMsg');

// 点击模态框外部关闭
window.onclick = function(event) {
  if (event.target === modal) {
    modal.style.display = "none";
  }
};

// 统一错误提示函数
function showError(msg) {
  errMsgDiv.innerHTML = ''; // 每次提交清空旧错误
  const errP = document.createElement('p');
  errP.textContent = msg;
  errMsgDiv.appendChild(errP);
}

// 表单提交处理函数
function handleAgeCheck(e) {
  e.preventDefault(); // 先阻止默认表单提交
  errMsgDiv.innerHTML = '';

  // 获取并格式化输入值
  const [dayInput, monthInput, yearInput] = Array.from(document.querySelectorAll('.ageGate')).map(i => i.value.trim());
  
  // 1. 验证输入格式是否合法
  const isDayValid = /^\d{2}$/.test(dayInput);
  const isMonthValid = /^\d{2}$/.test(monthInput);
  const isYearValid = /^\d{4}$/.test(yearInput);
  if (!isDayValid || !isMonthValid || !isYearValid) {
    showError('Invalid Credentials');
    return;
  }

  // 2. 准确计算用户年龄是否满18
  const birthDate = new Date(`${yearInput}-${monthInput}-${dayInput}`);
  const today = new Date();
  let age = today.getFullYear() - birthDate.getFullYear();
  // 处理生日未过的情况:比如今天是2024年5月,用户生日是2006年6月,实际未满18
  const hasBirthdayPassed = today.getMonth() > birthDate.getMonth() || 
                          (today.getMonth() === birthDate.getMonth() && today.getDate() >= birthDate.getDate());
  if (!hasBirthdayPassed) age--;

  if (age < 18) {
    showError('Invalid Credentials');
    return;
  }

  // 3. 验证通过,执行关闭逻辑
  btnSubmit.style.display = 'none';
  loading.classList.remove('hide');
  
  // 模拟加载动画后关闭模态框(实际项目可替换为接口请求/设置cookie逻辑)
  setTimeout(() => {
    modal.style.display = 'none';
    // 可选:设置cookie,下次打开页面不再显示年龄验证
  }, 1000);
}

// 绑定表单提交事件
form.addEventListener('submit', handleAgeCheck);

3. 关键修复点解释

  • ID匹配修正:把document.getElementById("myModal")改成document.getElementById("modal"),确保能正确获取模态框元素
  • 严谨的年龄计算:用Date对象结合月日判断用户是否真的满18岁,避免仅用年份判断的误差
  • 统一错误处理:每次提交先清空旧错误提示,避免重复堆积
  • 添加关闭逻辑:在验证通过的分支里,通过modal.style.display = 'none'关闭模态框,同时保留你原本的加载动画逻辑
  • 格式验证优化:用正则表达式验证输入是否符合DD/MM/YYYY的数字格式,提升验证准确性

4. HTML小优化建议

  • 把max-length改成标准HTML属性maxlength
  • 给输入框添加pattern属性,在浏览器层面做基础校验:
    <input class="ageGate" type="text" maxlength="2" placeholder="DD" pattern="\d{2}" required>
    <input class="ageGate" type="text" maxlength="2" placeholder="MM" pattern="\d{2}" required>
    <input class="ageGate" type="text" maxlength="4" placeholder="YYYY" pattern="\d{4}" required>
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 12:10:19