JavaScript重复密码验证场景下label标签被移除问题排查
注册页重复密码模块验证逻辑异常
问题表现
- 正常运行场景:注册操作时,先在「密码」输入框输入内容(无论是否满足8位长度要求),再在「重复密码」输入框输入内容会触发黄色背景错误提示,提示位于输入框上方、「Repeat Password」标签下方。两次输入密码一致时(无论第一个密码是否合法),黄色错误提示正常移除,「Repeat Password」标签保留;表单提交时触发的重复密码错误逻辑也可正常运行。
- 异常场景:
- 「重复密码」与「密码」输入框均为空时,「Repeat Password」标签会消失;比如所有字段留空点击提交,「Repeat Password」标签直接消失,也不会展示黄色错误提示。
- 所有输入均合法,表单提交重置后,「Repeat Password」标签同样会消失。
相关代码
JavaScript验证逻辑
/* Register Validation */ function checkField(field) { if (!field.checkValidity()) { addError(field); } else { removeError(field); } } function checkMatch() { const registerForm = document.getElementById("register-form"); const passwordOneInput = registerForm.passwordone; const passwordTwoInput = registerForm.passwordtwo; if (passwordOneInput.value !== passwordTwoInput.value) { if (passwordTwoInput.previousElementSibling && passwordTwoInput.previousElementSibling.className === 'error') { // error message already showing return; } const error = document.createElement('div'); error.innerHTML = passwordTwoInput.dataset.errorMsg; error.style.backgroundColor = 'yellow'; error.style.borderRadius = '0.2em'; error.style.width = 'fit-content'; error.className = 'error'; passwordTwoInput.parentNode.insertBefore(error, passwordTwoInput); } else { passwordTwoInput.previousElementSibling.remove(); } } function addError(field) { if (field.previousElementSibling && field.previousElementSibling.className === 'error') { // error message already showing return; } const error = document.createElement('div'); error.innerHTML = field.dataset.errorMsg; error.style.backgroundColor = 'yellow'; error.style.borderRadius = '0.2em'; error.style.width = 'fit-content'; error.className = 'error'; field.parentNode.insertBefore(error, field); } function removeError(field) { if (field.previousElementSibling && field.previousElementSibling.className === 'error') { field.previousElementSibling.remove(); } } window.addEventListener('load', function(e) { const registerForm = document.getElementById("register-form"); const emailInput = registerForm.emailregister; emailInput.dataset.errorMsg = 'Enter a valid email address'; const passwordOneInput = registerForm.passwordone; passwordOneInput.dataset.errorMsg = 'Password must be at least 8 characters'; const passwordTwoInput = registerForm.passwordtwo; passwordTwoInput.dataset.errorMsg = 'Password does not match'; const termsInput = registerForm.terms; termsInput.dataset.errorMsg = 'You must check the box to proceed'; emailInput.addEventListener('input', function(e) { checkField(emailInput); }); passwordOneInput.addEventListener('input', function(e) { checkField(passwordOneInput); }); passwordTwoInput.addEventListener('input', function(e) { checkMatch(); }); termsInput.addEventListener('input', function(e) { checkField(termsInput); }); registerForm.addEventListener('submit', function(e) { checkField(emailInput); checkField(passwordOneInput); checkMatch(); checkField(terms); if (!registerForm.checkValidity()) { e.preventDefault(); alert('Please fix form errors.');} else {registerForm.submit; registerForm.reset(); } }); });
页面HTML代码
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width,initial-scale=1.0"> <link rel="stylesheet" href="../normalize.css"> <link rel="stylesheet" href="index-styles.css"> <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.15.3/css/all.css" integrity="sha384-SZXxX4whJ79/gErwcOYf+zWLeJdY/qpuqC4cAa9rOGUstPomtqpuNWT9wdPEn2fk" crossorigin="anonymous"> <script src="login.js"></script> <title>Play2Learn Login</title> </head> <body> <header> <h1><img src="logo.png" alt="logo"></h1> <nav> <ul> <li><a class="border" href="index.html">Home</a></li> <li id="games-li"><a class="border" href="#">Games</a> <ul id="games-ul"> <li><a href="games/anagram-hunt.html">Anagram Hunt </a></li> <li><a href="games/math-facts.html">Math Facts Practice</a></li> </ul> </li> <li><a class="border" href="about.html">About</a></li> <li><a href="login.html">Login </a></li> </ul> </nav> </header> <main> <div id="login-div" class="form-div"> <h2>Log In</h2> <article id="article3"> <form id="login-form" method="post" action="javascript:alert('Form Submitted. You are now logged in.')" novalidate> <div> <label for="emaillogin">Email:</label> <input type="email" name="emaillogin" id="emaillogin" size="25" required> </div> <div> <label for="passwordlogin">Password:</label> <input type="password" name="passwordlogin" id="passwordlogin" size="25" minlength="8" required> </div> <div> <a href="#" id="login-toggle">Need an account? Register</a> </div> <div> <input type="submit" name="login-submit" id="login-submit" value="Login"> </div> </form> </article> </div> <div id="register-div" class="form-div"> <h2>Register</h2> <article id="article3"> <form id="register-form" method="post" action="javascript:alert('Form Submitted. Check your email to complete registration.')" novalidate> <div> <label for="emailregister">Email:</label> <input type="email" name="emailregister" id="emailregister" size="25" required> </div> <div> <label for="passwordone">Password:</label> <input type="password" name="passwordone" id="passwordone" minlength="8" size="25" required> </div> <div> <label for="passwordtwo">Repeat Password:</label> <input type="password" name="passwordtwo" id="passwordtwo" minlength="8" size="25" required> </div> <div> <input type="checkbox" name="terms" id="terms" required> <label for="terms" class="required"> I am at least 8 years old.</label> </div> <div> <a href="#" id="register-toggle">Already have an account? Login</a> </div> <div> <input type="submit" name="register-submit" id="register-submit" value="Register"> </div> </form> </article> </div> </main> <footer> <div class="footer"> © 2021 Play2Learn <a href="contact-us.html" title="Contact Us"><i class="fas fa-envelope-square"></i></a> <a href="https://instagram.com" title="Instagram"><i class="fab fa-instagram-square"></i></a> <a href="https://twitter.com" title="Twitter"><i class="fab fa-twitter-square"></i></a> <a href="https://facebook.com" title="Facebook"><i class="fab fa-facebook-square"></i></a> </div> </footer> </body> </html>
问题原因与修复方案
根因
checkMatch函数的else分支没有判断被移除的元素是否是错误提示元素,直接删除了重复密码输入框的前一个相邻元素。当两个密码输入框都为空时,二者值相等会进入else分支,此时重复密码输入框的前一个元素就是「Repeat Password」标签,会被误删。
修复代码
只需要修改checkMatch函数的else分支,增加和removeError一致的判断逻辑即可:
function checkMatch() { const registerForm = document.getElementById("register-form"); const passwordOneInput = registerForm.passwordone; const passwordTwoInput = registerForm.passwordtwo; if (passwordOneInput.value !== passwordTwoInput.value) { // 原有逻辑保持不变 if (passwordTwoInput.previousElementSibling && passwordTwoInput.previousElementSibling.className === 'error') { return; } const error = document.createElement('div'); error.innerHTML = passwordTwoInput.dataset.errorMsg; error.style.backgroundColor = 'yellow'; error.style.borderRadius = '0.2em'; error.style.width = 'fit-content'; error.className = 'error'; passwordTwoInput.parentNode.insertBefore(error, passwordTwoInput); } else { // 修改部分:仅当前一个元素是错误提示时才删除 if (passwordTwoInput.previousElementSibling && passwordTwoInput.previousElementSibling.className === 'error') { passwordTwoInput.previousElementSibling.remove(); } } }
内容的提问来源于stack exchange,提问作者Hawkins.bp
相关产品推荐
相关产品推荐

