仅当无重复邮箱时动态添加输入字段的功能BUG排查
邮箱重复校验功能BUG修复
问题描述
我正在开发一个邮箱重复校验功能:只有当所有输入的邮箱都不重复时,才能点击「添加更多」按钮添加新的输入字段。目前功能大体可用,但存在一处BUG。
BUG重现步骤
- 随意填写第一行输入字段,点击「添加更多」按钮;
- 填写第二行输入字段:若输入与第一行相同的邮箱,按钮会被禁用;若输入其他邮箱,按钮恢复启用,再次点击「添加更多」按钮;
- 填写第三行输入字段,输入一个新的邮箱;
- 修改第二行的邮箱为第三行的邮箱,按钮会被禁用;此时若修改第一行邮箱(删除任意字符),按钮却恢复启用,但此时第二、三行邮箱仍重复,不符合预期。
原JS代码
let clone = document.querySelector('.js-form-content').cloneNode(true); document.querySelector('.js-form-content').remove(); let btn = document.querySelector('.add-more'); let count = 0; function emailHandler(clonedElement) { const email = clonedElement.querySelector(`input[type="email"]`); const allEmails = document.querySelectorAll(`input[type="email"]`); email.addEventListener('keyup', (event) => { const emails = document.querySelectorAll(`input[type="email"]`); let emailsValues = [] emails.forEach((email, index) => { if (!email.isSameNode(event.target)) { emailsValues.push(email.value) } }) console.log(emailsValues); if (emailsValues.includes(event.target.value) && email.value.length > 0) { this.flag = false; btn.setAttribute('disabled', ' '); } else { this.flag = true btn.removeAttribute('disabled', ' '); } }) } function createElement(clonedElement) { clonedElement.classList.remove('d-none'); clonedElement.querySelectorAll('[name]').forEach(input => { }) clonedElement.querySelectorAll('[name]').forEach(input => { const name = input.getAttribute('name'); input.setAttribute('name', `participant[${count}][${name}]`); }) count ++; document.querySelector('.form-content-holder').appendChild(clonedElement); } function addNewFields () { // btn.setAttribute('disabled', ' '); const clonedElement = clone.cloneNode(true); createElement(clonedElement); emailHandler(clonedElement); const inputs = document.querySelectorAll('.input-participant-data'); } btn.addEventListener('click', () => addNewFields());
问题分析
原代码的核心问题在于只校验当前输入框的值是否和其他输入框重复,而没有检查所有输入框之间是否存在重复。当修改第一行邮箱时,代码只判断第一行的值是否和其他行重复,完全忽略了第二、三行之间的重复情况,导致错误启用按钮。
正确的逻辑应该是:每次输入变化时,收集所有非空邮箱值,检查整个集合中是否存在重复值。只要有任意两个邮箱重复,就禁用按钮;否则启用按钮。
修复后的JS代码
let clone = document.querySelector('.js-form-content').cloneNode(true); document.querySelector('.js-form-content').remove(); let btn = document.querySelector('.add-more'); let count = 0; // 全局校验所有邮箱是否重复的函数 function checkEmailDuplicates() { const emails = document.querySelectorAll(`input[type="email"]`); const emailValues = Array.from(emails) .map(input => input.value.trim()) .filter(value => value !== ''); // 过滤空值 // 利用Set去重特性判断是否存在重复 const hasDuplicates = new Set(emailValues).size !== emailValues.length; hasDuplicates ? btn.setAttribute('disabled', '') : btn.removeAttribute('disabled'); } function emailHandler(clonedElement) { const email = clonedElement.querySelector(`input[type="email"]`); // 监听输入事件,触发全局校验 email.addEventListener('keyup', checkEmailDuplicates); // 监听input事件,覆盖粘贴、输入法输入等场景 email.addEventListener('input', checkEmailDuplicates); } function createElement(clonedElement) { clonedElement.classList.remove('d-none'); clonedElement.querySelectorAll('[name]').forEach(input => { const name = input.getAttribute('name'); input.setAttribute('name', `participant[${count}][${name}]`); }); count++; document.querySelector('.form-content-holder').appendChild(clonedElement); } function addNewFields() { const clonedElement = clone.cloneNode(true); createElement(clonedElement); emailHandler(clonedElement); // 添加新字段后立即校验一次,确保状态正确 checkEmailDuplicates(); } btn.addEventListener('click', addNewFields); // 页面初始化时执行一次校验 checkEmailDuplicates();
修复说明
- 全局校验逻辑:新增
checkEmailDuplicates函数,统一收集所有非空邮箱值,通过Set判断是否存在重复,以此控制按钮状态,彻底解决局部校验的漏洞。 - 完善事件监听:同时监听
keyup和input事件,覆盖键盘输入、鼠标粘贴、输入法联想等多种输入场景。 - 补充校验时机:在页面初始化、添加新字段后都执行校验,确保按钮状态始终符合当前输入情况。
内容的提问来源于stack exchange,提问作者Marius Gardelli
相关产品推荐
相关产品推荐

