Node.js中SPA用toastr时'$.extend is not a function'错误修复
解决toastr插件"$.extend is not a function"错误的方案
你遇到的问题核心在于把前端插件拿到Node.js后端代码里调用了,这完全搞错了toastr的运行环境!咱们一步步理清楚:
问题根源
toastr是纯前端插件,依赖浏览器的DOM环境和全局的jQuery对象(也就是页面里的window.$)。但你在后端的tryController里用require('toastr')并调用toastr.success(),此时后端Node环境既没有浏览器DOM,也没有前端的全局jQuery,自然会报$.extend is not a function——因为后端的jquery模块和前端页面里的jQuery根本不是一回事儿。
正确的解决方案
第一步:清理后端代码
把后端里和jquery、toastr相关的代码全部删掉,后端只负责处理表单提交、发送邮件,然后给前端返回状态即可:
// 删掉这两行无用的require: // const jquery = require('jquery'); // const toastr = require('toastr'); app.post('/', urlencodedParser, function (req, res) { console.log(req.body); main(req.body.nameContact, req.body.emailContact, req.body.subjectContact, req.body.messageContact) .then(() => { console.log("Email Sended"); // 给前端返回成功状态(用JSON更适合AJAX交互) res.json({ success: true, msg: "邮件已成功发送!" }); }, err => { console.log("Email Error: " + err); // 返回失败状态 res.json({ success: false, msg: "邮件发送失败,请稍后重试" }); }) .catch(console.error); });
第二步:前端用AJAX提交表单并调用toastr
修改你的index.ejs,用AJAX提交表单(避免页面刷新),然后根据后端返回的结果触发toastr通知:
<!-- 保持已有的jQuery和toastr引入,别忘了加toastr的样式 --> <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/2.0.1/js/toastr.js"></script> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/2.0.1/css/toastr.css"> <!-- 给表单加个ID方便选择 --> <form id="contactForm" method="POST"> <!-- 你的表单内容 --> <button type="submit">提交</button> </form> <script> $(function() { // 监听表单提交事件 $('#contactForm').submit(function(e) { // 阻止默认的表单刷新跳转 e.preventDefault(); // 获取表单数据 const formData = $(this).serialize(); // 发送AJAX请求 $.post('/', formData, function(response) { if (response.success) { // 成功时显示通知 toastr.success(response.msg, '操作成功'); // 可选:重置表单 $('#contactForm')[0].reset(); } else { // 失败时显示错误通知 toastr.error(response.msg, '操作失败'); } }).fail(function() { // 网络异常时的提示 toastr.error('网络连接异常,请稍后重试', '错误'); }); }); }); </script>
备选方案:页面刷新后显示通知
如果你不想用AJAX,想保持原有的页面跳转逻辑,也可以让后端跳转时带参数,前端加载时判断参数并显示通知:
- 后端修改跳转代码:
res.redirect('#contactForm?success=1') - 前端添加页面加载判断:
$(function() { const params = new URLSearchParams(window.location.search); if (params.get('success') === '1') { toastr.success('邮件发送成功!', '成功'); } });
为什么之前的方法不行?
- 后端
require('jquery')得到的是Node环境下的jQuery(需要结合jsdom才能模拟浏览器,但完全没必要),和前端页面里的jQuery是两个独立的对象。 - toastr是为浏览器设计的,必须在前端页面中运行,依赖浏览器的
window对象和全局$,后端调用它自然找不到需要的方法。
内容的提问来源于stack exchange,提问作者Oğuz Özdemir
相关产品推荐
相关产品推荐

