JavaScript+CSS实现的Toast通知在Node.js+Express+Passport登录页运行异常
登录页复用Toast组件报错问题及修复方案
在JavaScript课程项目中,我开发了支持汽车增删、列表展示的管理页面,功能跑通后又基于Express、Passport、MongoDB(使用Mongoose连接数据库)实现了登录页功能。
原有可正常运行的Toast组件代码
汽车管理页面原生JS+CSS实现的Toast通知组件,在用户增删汽车时运行正常,代码如下:
Toast.js 代码
const Toast = { init() { this.hideTimeout = null; this.el = document.createElement('div'); this.el.className = 'toastNotification'; document.body.appendChild(this.el); }, show(message, state) { clearTimeout(this.hideTimeout); this.el.textContent = message; this.el.className = 'toastNotification toastNotification--visible'; if (state) { this.el.classList.add(`toastNotification--${state}`); } this.hideTimeout = setTimeout(() => { this.el.classList.remove('toastNotification--visible') }, 2000); } }; document.addEventListener('DOMContentLoaded', () => Toast.init()); export default Toast;
对应CSS代码
.toastNotification { font-family: Poppins, sans-serif; font-weight: 300; position: fixed; right: 10%; top: 0; margin: auto; padding: 1.2em; background: #00afb9; font-size: 1.1em; color: #fdfcdc; border-radius: 5px; box-shadow: 0 0 10px #fed9b7; visibility: hidden; opacity: 0; transition: opacity 0.5s, top 0.5s, visibility 0.5s; } .toastNotification--visible { top: 2%; opacity: 1; visibility: visible; } .toastNotification--excluded { background: #f07167; color: #fdfcdc; } .toastNotification--added { background: #00afb9; color: #fdfcdc; } @media (max-width: 500px) { .toastNotification { padding: 0.6em; font-size: 0.6em; box-shadow: 0 0 5px #fed9b7; } }
汽车管理页面调用示例
Toast.show('Carro adicionado com sucesso!', 'added'); // 新增成功提示 Toast.show('Carro excluído com sucesso.', 'excluded'); // 删除成功提示
登录页复用Toast的实现代码
服务端登录校验逻辑(Express+Passport)
app.post('/login', (req, res, next) => { passport.authenticate('local', (err, user, info) => { if (err) { return next(err); } if (!user) { return res.redirect('/login?info=' + info); } req.logIn(user, function (err) { if (err) { return next(err); } return res.redirect('/carshop'); }); })(req, res, next); });
前端登录错误处理脚本
const urlParams = new URLSearchParams(window.location.search); const info = urlParams.get('info'); if (info) { // 登录信息错误时的处理逻辑 }
遇到的问题
- 导入Toast后直接在错误处理逻辑中调用
Toast.show方法,报错:Uncaught TypeError: Cannot set property 'textContent' of undefined,但登录页加载时body中已经生成了toast的div元素 - 在错误处理逻辑中重新调用
Toast.init后Toast能显示,但是动画完全失效,通知弹出后一直停留在页面上
问题原因
- 提交错误账号密码后页面重载,Toast对象的this指向异常
- 重载后的页面没有执行Toast.init方法,导致Toast.show没有可操作的DOM元素
- 重复调用init会生成多个toast DOM元素,CSS选择器匹配异常导致动画失效
最终修复方案
步骤1:HTML中硬编码Toast元素
<div class="toastNotification" id="toast"></div>
步骤2:修改Toast.js逻辑,不依赖this绑定的DOM元素
const Toast = { init() { this.hideTimeout = null; this.el = document.createElement('div'); this.el.className = 'toastNotification'; this.el.id = 'toast'; document.body.appendChild(this.el); }, show(message, state) { clearTimeout(this.hideTimeout); const $toast = document.querySelector('#toast'); $toast.textContent = message; $toast.className = 'toastNotification toastNotification--visible'; if (state) { $toast.classList.add(`toastNotification--${state}`); } this.hideTimeout = setTimeout(() => { $toast.classList.remove('toastNotification--visible') }, 2000); } };
步骤3:登录页调用代码
import Toast from "./toast/toast.js"; const urlParams = new URLSearchParams(window.location.search); const info = urlParams.get('info'); if (info) { Toast.show('Dados incorretos', 'excluded'); }
内容的提问来源于stack exchange,提问作者thebigfundamentals
相关产品推荐
相关产品推荐

