You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 07:49:23