#constraint-validation { --color-main: #9e9e9e; --color-focus: #26a69a; --color-error: #f44336; width: 80%; .inputArea { position: relative; height: torem(52px); margin-top: torem(32px); .label { position: absolute; top: 0; left: 0; color: var(--color-main); font-size: torem(16px); line-height: torem(32px); transition: 0.2s ease-out; } .input { display: block; width: 100%; height: torem(32px); border: 0; border-bottom: 1px solid var(--color-main); padding: 0; margin-bottom: torem(8px); &:focus { outline: none; } } .helper { display: block; color: var(--color-error); font-size: torem(12px); line-height: torem(12px); opacity: 0; transition: 0.2s ease-out; } &.focus { .label { color: var(--color-focus); font-size: torem(12px); line-height: torem(16px); transform: translateY(torem(-16px)); } .input { border-bottom: 1px solid var(--color-focus); } } &.invalid { .input { border-bottom: 1px solid var(--color-error); } .helper { opacity: 1; } } } .button { margin-top: torem(32px); .submit { height: torem(36px); color: color(white); font-size: torem(14px); line-height: torem(36px); background-color: var(--color-focus); border: 0; border-radius: torem(3px); padding: 0 torem(16px); cursor: pointer; } } }
/** * 表单聚焦 */ function focus(e) { e.target.closest('.inputArea').classList.add('focus'); } /** * 表单失去焦点 */ function blur(e) { const { value } = e.target; if (!value) { e.target.closest('.inputArea').classList.remove('focus'); } } /** * 表单输入变动 */ function change(e) { const input = e.target; input.closest('.inputArea').classList.remove('invalid'); // customValidity设置后将一直保存,需手动清理,然后执行验证 if (input.validity.customError) { input.setCustomValidity(''); } input.checkValidity(); } /** * 表单invalid处理 */ function invalid(e) { e.preventDefault(); const input = e.target; const inputType = input.getAttribute('type'); const inputArea = input.closest('.inputArea'); const helper = inputArea.querySelector('.helper'); // 自定义相对valueMissing更明确的提示 if (input.validity.valueMissing) { if (inputType === 'email') { input.setCustomValidity('Email Required'); } else if (inputType === 'password') { input.setCustomValidity('Password Required'); } } // 相对patternMismatch更明确的提示 if (input.validity.patternMismatch && inputType === 'password') { helper.innerHTML = `${input.validationMessage.slice(0, -1)}:${input.title}`; } else { helper.innerHTML = input.validationMessage; } inputArea.classList.add('invalid'); } /** * 表单提交,只有完成Constraint Validation才会触发submit事件 */ function submit(e) { e.preventDefault(); const form = e.target; Array.from(form.querySelectorAll('.inputArea')).forEach((elem) => { elem.classList.remove('focus', 'invalid'); }); form.reset(); } document.addEventListener('DOMContentLoaded', () => { const form = document.querySelector('#constraint-validation'); form.addEventListener('submit', submit, false); Array.from(document.querySelectorAll('.input')).forEach((input) => { input.addEventListener('focus', focus, false); input.addEventListener('blur', blur, false); input.addEventListener('change', change, false); input.addEventListener('invalid', invalid, false); }); }, false);