JavaScript表单required校验失效与事件绑定报错排查
问题根因
两个异常的核心原因分别是选择器匹配错误、事件绑定对象和逻辑拦截时机错误:
- 选择器
button[type=submit]匹配失败:你的提交控件是<input type="submit">,不是<button>标签,页面中不存在符合该选择器的元素,因此返回null,绑定事件时直接抛出空指针错误:
Uncaught TypeError: Cannot read properties of null (reading 'addEventListener')
- 选择器
[type=submit]下required校验失效:你给提交按钮绑定了click事件,回调第一行就执行e.preventDefault(),直接拦截了所有默认行为——浏览器原生的表单校验逻辑本来是在表单提交前触发,被提前拦截后根本不会执行,因此空值也能直接进入后续业务逻辑。 - 原代码额外存在选择器错误:把类名为
rightside-content的普通div当作表单元素,该元素无法触发submit事件。
正确实现方案
不要监听提交按钮的click事件,改为监听<form>元素的submit事件:
- 浏览器会在
submit事件触发前自动执行所有原生校验(required、pattern等),校验不通过时直接弹出提示、不会进入事件回调。 - 只有所有校验规则全部满足,才会执行你写的提交逻辑,完全符合预期。
同时修复原代码的隐性bug:全局初始化的user是同一个对象引用,多次提交时数组里存储的所有用户数据都会被覆盖为最后一次提交的值,需要在提交回调内部新建用户对象;冗余的count变量可以删除,直接用数组push方法即可维护存储顺序。
修复后完整代码
HTML部分(无需修改)
<div class="rightside-content"> <div class="signup-title"> <h1>Sign up</h1> </div> <form class="join-form"> <ul> <li><input type="text" name="username" class="username" placeholder="Username" required></li> <li><input type="text" name="fullname" class="fullname" placeholder="Full Name" required></li> <li><input type="email" name="email" class="email" placeholder="Email Address" pattern=".+@gmail\.com" required></li> <li><input type="text" name="phone" class="phone" placeholder="Phone Number" required></li> <li><input type="text" name="postcode" class="postcode" placeholder="Post Code" required></li> <li><input type="password" name="password" class="password" placeholder="Enter a password" required></li> </ul> <input type="submit"> </form> </div>
JS部分
// 获取真实表单元素绑定事件,单独获取容器用于展示成功提示 const registerForm = document.querySelector(".join-form"); const successContainer = document.querySelector(".rightside-content"); const userName = document.querySelector(".username"); const fullName = document.querySelector(".fullname"); const emailAddress = document.querySelector(".email"); const contactNumber = document.querySelector(".phone"); const postCode = document.querySelector(".postcode"); const Password = document.querySelector(".password"); let users = []; // 监听表单submit事件,校验通过才会进入回调 registerForm.addEventListener("submit", (e) =>{ e.preventDefault(); // 每次提交新建独立用户对象,避免引用覆盖问题 const user = { userName: userName.value, fullName: fullName.value, emailAddress: emailAddress.value, contactNumber: Number(contactNumber.value), postCode: Number(postCode.value), Password: Password.value }; users.push(user); console.log(users); console.log(users.length); // 展示注册成功提示 successContainer.innerHTML = 'Thank you for joining!'; successContainer.style.fontSize = '1.5rem'; successContainer.style.fontFamily = 'Segoe UI, Tahoma, Geneva, Verdana, sans-serif'; successContainer.style.textAlign = 'center'; successContainer.style.marginTop = '50%'; })
内容的提问来源于stack exchange,提问作者paparonnie
相关产品推荐
相关产品推荐

