从缓存恢复HTML5表单值后元素误判为valid,如何修复?
表单缓存恢复后验证状态异常的解决方法
我通过以下代码将表单数据保存到localStorage:
contact.form.oninput = (event) => { contact.saveFormToBrowserCache(); } static async saveFormToBrowserCache() { let formElements = Tools.qSA("main.contact .contactForm input:not([type=checkbox]), main.contact .contactForm textarea"); let o = {}; let cacheKey = await Tools.sha256(contact.formCacheKey); formElements.forEach((input) => { let inputValue = (input as HTMLInputElement).value let key = input.name; let value = inputValue; if (value !== "") { o = { ...o, [key]: value.trim() } } }); ls.set(cacheKey, o, { encrypt: true }); }
页面加载时用下面的代码恢复缓存数据:
async restoreFormFromCache() { let cacheKey = await Tools.sha256(contact.formCacheKey); let formVariables = ls.get(cacheKey, { decrypt: true }) as Object; if (formVariables) { Object.entries(formVariables).forEach(entry => { const [key, value] = entry; let element = Tools.qS("main.contact .contactForm [name=" + key + "]") as HTMLInputElement; element.value = value.trim(); }); this.messageCurrentChars.innerHTML = this.textarea.value.length.toString(); this.autoSizeTextArea(this.textarea); } }
但恢复后,像<input name=name inputmode=text autocomplete="honorific-suffix given-name additional-name family-name" title="..." type=text minlength=2 required>这类带minlength、required属性的输入框,哪怕只输入1个字符,也会被:valid CSS选择器标记为有效,手动输入时验证却是正常的。
解决方法
直接通过JS修改value不会触发浏览器的表单验证流程,所以需要手动触发验证来更新:valid/:invalid状态,有三种常用方式:
- 调用元素的验证方法
在设置完element.value后,调用checkValidity(),这个方法会触发验证并更新状态,不会弹出提示:
Object.entries(formVariables).forEach(entry => { const [key, value] = entry; let element = Tools.qS("main.contact .contactForm [name=" + key + "]") as HTMLInputElement; element.value = value.trim(); // 触发验证更新状态 element.checkValidity(); });
- 触发input事件
模拟用户输入的input事件,让浏览器自动重新计算验证状态:
Object.entries(formVariables).forEach(entry => { const [key, value] = entry; let element = Tools.qS("main.contact .contactForm [name=" + key + "]") as HTMLInputElement; element.value = value.trim(); // 触发input事件 element.dispatchEvent(new Event('input', { bubbles: true })); });
- 调用reportValidity()(带提示)
如果需要在状态无效时显示浏览器默认的验证提示框,可以用这个方法:
Object.entries(formVariables).forEach(entry => { const [key, value] = entry; let element = Tools.qS("main.contact .contactForm [name=" + key + "]") as HTMLInputElement; element.value = value.trim(); // 触发验证并显示提示 element.reportValidity(); });
原理
浏览器的表单验证状态(:valid/:invalid)默认只在用户交互(比如输入、提交)时更新,通过JS直接修改value属于非用户触发的变更,不会自动触发验证逻辑,手动调用验证方法或模拟输入事件就能让浏览器重新校验元素是否符合规则。
内容的提问来源于stack exchange,提问作者Sascha Grindau
相关产品推荐
相关产品推荐

