使用Node.js与EJS时如何避免登录模态框在验证出错时关闭
弹窗登录表单验证错误自动关闭问题解决方法
根本原因
你当前使用的是表单同步提交逻辑,提交后会触发整页刷新,页面刷新后默认不会给弹窗元素添加active激活类,所以弹窗会自动关闭,用户无法看到返回的验证错误提示。
解决方案1:服务端渲染直接激活弹窗(改动最小)
无需修改表单提交逻辑,只需要调整EJS模板的弹窗渲染规则,存在错误时默认给弹窗添加激活类即可:
<!-- 将原有弹窗div修改为如下逻辑,存在错误时默认添加active类 --> <div class="modal <%= errors && errors.length > 0 ? 'active' : '' %>"> <div class="modal__box"> <form id="login-form" action="/auth/login" method="POST"> <h2>Login</h2> <% errors.forEach(function(message) { %> <div class="alert alert__danger"> <p><%= message %></p> </div> <% }) %> <input type="email" placeholder="email" name="email"> <input type="password" placeholder="password" name="password"> <button id="modal-submit" class="btn">Login</button> <span class="modal__close"><i class="fas fa-times"></i></span> </form> </div> </div>
注意:需要给input补充name属性,否则表单提交后后端无法拿到对应字段值。
解决方案2:异步提交表单(体验更优)
拦截表单默认提交行为,用AJAX异步提交数据,全程不刷新页面,弹窗不会自动关闭。
修改前端JS代码
class Nav { constructor(){ this.modalBtn = document.querySelector('.modal__btn') this.modalBg = document.querySelector('.modal') this.modalCloseBtn = document.querySelector('.modal__close') this.loginForm = document.querySelector('#login-form') this.events() } events() { this.modalBtn.addEventListener('click', () => this.modalOpen()) this.modalCloseBtn.addEventListener('click', () => this.modalClose()) // 新增表单提交事件监听 this.loginForm.addEventListener('submit', (e) => this.handleLoginSubmit(e)) } modalOpen() { this.modalBg.classList.add('active') } modalClose() { this.modalBg.classList.remove('active') // 关闭弹窗时清空历史错误提示 document.querySelectorAll('.alert__danger').forEach(el => el.remove()) } // 新增异步提交处理方法 async handleLoginSubmit(e) { e.preventDefault() // 阻止默认同步提交刷新页面 const formData = new FormData(this.loginForm) const res = await fetch('/auth/login', { method: 'POST', body: formData }) const result = await res.json() // 存在验证错误时直接渲染到弹窗内 if(result.errors) { const errorHtml = result.errors.map(msg => `<div class="alert alert__danger"><p>${msg}</p></div>`).join('') this.loginForm.querySelector('h2').insertAdjacentHTML('afterend', errorHtml) return } // 登录成功跳转页面 window.location.href = result.redirectUrl || '/dashboard' } } export default Nav
调整后端接口逻辑(以Express为例)
app.post('/auth/login', (req, res) => { const errors = [] // 你的原有验证逻辑,将错误信息存入errors数组 if(!req.body.email) errors.push('请输入邮箱地址') if(!req.body.password) errors.push('请输入登录密码') if(errors.length > 0) { // 判断是否为异步请求,是则返回JSON格式错误 if(req.xhr || req.headers.accept.includes('json')) { return res.json({ errors }) } // 兼容同步提交场景,返回原页面带错误信息 return res.render('当前页面模板名', { errors }) } // 验证通过逻辑 if(req.xhr || req.headers.accept.includes('json')) { return res.json({ redirectUrl: '/dashboard' }) } res.redirect('/dashboard') })
内容的提问来源于stack exchange,提问作者Julie Kimuli
相关产品推荐
相关产品推荐

