You need to enable JavaScript to run this app. HTML拖放场景下调用axios POST请求,parcel打包后报sendNewCard未定义
优惠活动
大模型
产品
解决方案
定价
更多

HTML拖放场景下调用axios POST请求,parcel打包后报sendNewCard未定义

看板系统拖放功能集成后端同步请求问题

已实现的基础能力

目前已完成可正常运行的看板卡片拖放逻辑,核心代码位于response.js:

function allowDrop(ev) {
    ev.preventDefault();
}
  
function drag(ev) {
    ev.dataTransfer.setData("text", ev.target.id);
}

const drop = async(ev, el) => {
    ev.preventDefault();
    var data = ev.dataTransfer.getData("text");
    el.appendChild(document.getElementById(data));
    
    newSection = el.parentElement.childNodes[0].childNodes[0].textContent;
    sortItems(el);
}
  • 拖放逻辑通过PUG渲染生成的HTML内联事件绑定,对应代码为:
ondrop='drop(event, this)' ondragover='allowDrop(event)'

待实现需求

拖放操作完成后,需要同步发送Axios POST请求,将卡片新的所属看板列信息同步到后端,请求结构为:

const res = await axios({
    method: 'POST',
    url: 'http://127.0.0.1:3000/api/1/projects/updateCardPlace',
    data: {
        cardID, // 暂未获取该参数,可暂时忽略
        newSection
    }
});

开发环境配置

  • 打包工具使用Parcel,package.json中的JS构建脚本配置为:
"build:js": "parcel watch ./public/js/index.js --out-dir --public-url ./public/js --out-file bundle.js"
  • 已确认PUG渲染的HTML页面正确引入了构建生成的bundle.js文件

已尝试方案与报错现象

先后尝试两种自定义请求方法的接入方式:

  1. 将原本定义在login.js中的sendNewCard方法导入到入口文件index.js
  2. 直接将sendNewCard方法写入打包生成的bundle.js
    两种方案均触发报错:Uncaught ReferenceError: sendNewCard is not defined

目前已在卡片的ondrop内联事件中添加对sendNewCard方法的调用,bundle.js中实际打包生成的sendNewCard代码结构如下:

var sendNewCard = /*#__PURE__*/function () {
  var _ref = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee(el) {
    var res;
    return regeneratorRuntime.wrap(function _callee$(_context) {
      while (1) {
        switch (_context.prev = _context.next) {
          case 0:
            if (!(el != 1)) {
              _context.next = 13;
              break;
            }

            newSection = el.parentElement.childNodes[0].childNodes[0].textContent;
            _context.prev = 2;
            _context.next = 5;
            return (0, _axios.default)({
              method: 'POST',
              url: 'http://127.0.0.1:3000/api/1/projects/updateCardPlace',
              data: {
                cardID: cardID,
                newSection: newSection
              }
            });

          case 5:
            res = _context.sent;
            if (res.data.status === 'Success') {
              (0, _alerts.showAlert)('success', 'Successfully transferred.');
            } else {
              (0, _alerts.showAlert)('error', 'Unsuccessfully transferred.');
            }
            _context.next = 13;
            break;

          case 9:
            _context.prev = 9;
            _context.t0 = _context["catch"](2);
            console.log(_context.t0.message);
            (0, _alerts.showAlert)('error', 'Unsuccessfully transferred.');

          case 13:
          case "end":
            return _context.stop();
        }
      }
    }, _callee, null, [[2, 9]]);
  }));

  return function sendNewCard(_x) {
    return _ref.apply(this, arguments);
  };
}();

exports.sendNewCard = sendNewCard;

问题根因

Parcel默认按照CommonJS模块化规范打包代码,模块内部定义的sendNewCard变量属于模块作用域,不会自动挂载到浏览器全局window对象上;而HTML内联事件(如ondrop)只能访问全局作用域内的方法,因此会触发未定义报错。

可落地的解决方式

  • 推荐方案:取消内联事件绑定,改用JS动态绑定事件
    移除HTML属性中的ondrop='drop(event, this)'写法,为所有可放置的看板列元素添加统一标识类名,在入口JS中通过DOM选择器查找元素并动态绑定事件,全程不需要将方法挂载到全局作用域,完全符合模块化开发规范:

    // 入口JS中执行一次即可
    const dropTargets = document.querySelectorAll('.kanban-drop-zone');
    dropTargets.forEach(target => {
      target.addEventListener('dragover', allowDrop);
      target.addEventListener('drop', (ev) => drop(ev, target));
    })
    

    绑定完成后,直接在原有drop方法内部调用请求逻辑即可,无需跨作用域查找方法。

  • 兼容方案:手动将方法挂载到全局对象
    如果暂时不想修改现有HTML的内联绑定逻辑,只需要在源文件中sendNewCard定义完成后,手动将方法挂载到window对象上即可。注意不要直接修改打包生成的bundle.js,否则下次Parcel重新构建时改动会被覆盖:

    // 源文件中添加
    window.sendNewCard = sendNewCard;
    
  • 极简方案:直接将请求逻辑集成到原有drop方法内
    原有drop方法已经可以拿到newSection参数,完全不需要单独封装sendNewCard方法,直接把请求逻辑嵌入到drop方法末尾即可,减少不必要的跨作用域引用:

    const drop = async(ev, el) => {
      ev.preventDefault();
      var data = ev.dataTransfer.getData("text");
      const draggedCard = document.getElementById(data);
      el.appendChild(draggedCard);
      
      const newSection = el.parentElement.childNodes[0].childNodes[0].textContent;
      sortItems(el);
    
      // 直接嵌入请求逻辑
      try {
        // 从DOM卡片元素上读取卡片ID,不需要依赖全局变量
        const cardID = draggedCard.dataset.cardId;
        const res = await axios({
          method: 'POST',
          url: 'http://127.0.0.1:3000/api/1/projects/updateCardPlace',
          data: {
            cardID,
            newSection
          }
        });
        if (res.data.status === 'Success') {
          showAlert('success', 'Successfully transferred.');
        } else {
          showAlert('error', 'Unsuccessfully transferred.');
        }
      } catch (err) {
        showAlert('error', 'Unsuccessfully transferred.');
      }
    }
    

内容的提问来源于stack exchange,提问作者Matt

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.13 10:45:06