表单验证本地DOM操作遇Uncaught TypeError错误,求修复方案
表单验证报错:Uncaught TypeError: Cannot read properties of undefined (reading 'remove')
我需要实现以下表单验证功能:点击表单提交按钮时,若输入框为空或不符合邮箱格式,对应输入框旁需显示错误小图标,全程采用HTML、CSS、JS进行本地DOM操作。但目前运行时持续报错:Uncaught TypeError: Cannot read properties of undefined (reading 'remove'),相关代码如下:
错误代码
JavaScript
"use strict" const form = document.querySelector(".form"); const inputs = document.getElementsByTagName("input"); const errorImg = document.querySelectorAll(".error-img"); const submitBtn = document.getElementById("submit-btn"); submitBtn.addEventListener("click", (e) => { e.preventDefault(); if(!inputs.value){ errorImg.classList.remove("hidden"); } else { errorImg.classList.add("hidden"); } });
CSS
@import url(https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap); body{ margin: 0; background-image: url(images/bg-intro-desktop.png); background-color: rgba(255, 0, 0, .5); font-family: 'Poppins', sans-serif; } .container{ margin: 6rem auto; height: auto; width: 70%; display: grid; grid-template-areas: "left right" "left right"; grid-auto-columns: minmax(0, 32rem); } .left-container{ grid-area: left; } .left-heading{ color: white; font-size: 2.7rem; line-height: 3rem; font-weight: 700; position: relative; top: 30%; } .left-content{ color: white; font-size: .9rem; font-weight: 400; position: relative; top: 29%; } .right-container{ grid-area: right; } .right-top-container{ background-color: hsl(248, 32%, 49%); border-radius: .5rem; height: 11.5%; margin: auto auto 1.5rem auto; box-shadow: 0px 6px 1px rgba(0, 0, 0, .2); } .top-text-special{ color: white; font-weight: 600; font-size: .85rem; position: relative; top: 50%; left: 72%; transform: translate(-50%, -50%); } .top-text{ color: white; font-weight: 400; } .right-form{ background-color: white; height: 23rem; border-radius: .5rem; padding: 1.5rem; padding-top: 2.5rem; box-shadow: 0 7px 1px rgba(0, 0, 0, .15); display: grid; grid-template-areas: "fname" "lname" "email" "password" "submit-btn" "bottom-text"; } input{ font-family: 'Poppins', sans-serif; font-weight: 500; font-size: .8rem; position: relative; top: 50%; left: 50%; transform: translate(-50%, -50%); padding: 0 0 0 1.5rem; height: 130%; width: 90%; border: solid; border-width: .09rem; border-radius: .4rem; border-color: hsl(246, 25%, 77%); } .first-name-div{ grid-area: fname; margin: 0 0 7% 0; position: relative; } .last-name-div{ grid-area: lname; margin: 0 0 7% 0; position: relative; } .email-div{ grid-area: email; margin: 0 0 7% 0; position: relative; } .password-div{ grid-area: password; margin: 0 0 7% 0; position: relative; } .submit-btn-div{ grid-area: submit-btn; } #submit-btn{ position: relative; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 97.1%; height: 130%; border-radius: .4rem; background-color: hsl(154, 59%, 51%); border: none; color: white; box-shadow: 0 2px .5px rgba(0, 0, 0, .4); cursor: pointer; } .right-footer-text{ grid-area: bottom-text; } .footer-text{ position: relative; top: 50%; left: 58%; transform: translate(-50%, -50%); color: grey; font-size: .7rem; font-weight: 600; } .footer-span{ color: hsl(0, 100%, 74%); } #error-img{ position: absolute; top: 6px; right: 22px; } .hidden{ display: none; }
HTML
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>FrontEndMentor#3</title> <link rel="stylesheet" href="styles.css"> <link rel="shortcut icon" href="images/favicon-32x32.png" type="image/x-icon"> <link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap" rel="stylesheet"> </head> <body> <div class="container"> <div class="left-container"> <h1 class="left-heading">Learn to code by <br> watching others</h1> <p class="left-content">See how experienced developers solve problems in real-time. <br> Watching scripted tutorials is great, but understanding how <br> developers think is invaluable.</p> </div> <div class="right-container"> <div class="right-top-container"> <p class="top-text-special">Try it free 7 days <span class="top-text">then $20/mo. thereafter</span></p> </div> <form action="#" class="form"> <div class="right-form"> <div class="first-name-div"> <input type="text" name="fname" id="first-input" placeholder="First Name"> <img class="error-img hidden" src="images/icon-error.svg" alt="错误图标"> </div> <div class="last-name-div"> <input type="text" name="lname" id="last-input" placeholder="Last Name"> <img class="error-img hidden" src="images/icon-error.svg" alt="错误图标"> </div> <div class="email-div"> <input type="email" name="email-address" id="email" placeholder="example@email.com"> <img class="error-img hidden" src="images/icon-error.svg" alt="错误图标"> </div> <div class="password-div"> <input type="password" name="password" id="password" placeholder="Password"> <img class="error-img hidden" src="images/icon-error.svg" alt="错误图标"> </div> <div class="submit-btn-div"> <button type="submit" id="submit-btn">CLAIM YOUR FREE TRIAL</button> </div> <div class="right-footer-text"> <p class="footer-text">By clicking the button, you are agreeing to our <span class="footer-span">Terms and Services</span></p> </div> </div> </form> </div> </div> <script src="index.js"></script> </body> </html>
问题分析与修复
核心错误原因
inputs是类数组集合,不能直接取value:getElementsByTagName返回的是HTMLCollection,不是单个元素,必须遍历每个输入框才能获取对应的值。errorImg是类数组集合,不能直接调用classList:querySelectorAll返回的是NodeList,同样需要针对每个输入框对应的错误图标操作。
修复后的JavaScript代码
"use strict" const form = document.querySelector(".form"); const inputs = document.getElementsByTagName("input"); const errorImgs = document.querySelectorAll(".error-img"); const submitBtn = document.getElementById("submit-btn"); // 邮箱格式验证正则 const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; submitBtn.addEventListener("click", (e) => { e.preventDefault(); // 遍历每个输入框,对应各自的错误图标 Array.from(inputs).forEach((input, index) => { const errorImg = errorImgs[index]; let isValid = true; // 验证空值 if (!input.value.trim()) { isValid = false; } // 针对邮箱输入框做格式验证 if (input.type === 'email' && !emailRegex.test(input.value.trim())) { isValid = false; } // 控制错误图标显示/隐藏 if (!isValid) { errorImg.classList.remove("hidden"); } else { errorImg.classList.add("hidden"); } }); });
额外修复点
- CSS闭合问题:原CSS中
.hidden规则未闭合,已补充}。 - HTML表单结构:原代码中
form标签提前闭合,已调整为包裹整个表单内容,避免结构错误。
内容的提问来源于stack exchange,提问作者A Barlow
相关产品推荐
相关产品推荐

