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

JavaScript如何实现同一时间仅激活一个事件监听器、关闭其余冗余监听器

问题根因

你每次点击功能按钮时都会给表格新增一个独立的点击监听器,旧的监听器没有被主动移除,多个监听器同时存在就会触发不符合预期的交叉执行。你用once配置虽然解决了冲突,但监听器单次触发后自动销毁,自然无法支持连续放置多个同类元素的需求。

解决方案

不要每次点击按钮都给表格绑定新的监听器,改为全局记录当前操作模式,表格仅绑定一个统一的点击监听器,根据当前模式执行对应逻辑,改动后的代码如下:

// 新增全局变量记录当前操作模式,可选值:src(选起点)/des(选终点)/wall(放墙)/null(无操作)
let currentMode = null;
const table = document.querySelector('table');
const rows = document.querySelectorAll('tr');
const rowsArray = Array.from(rows);

// 页面初始化时只绑定一次表格点击监听器
table.addEventListener('click', (event) => {
  if (!currentMode) return; // 没有选中操作模式直接返回
  const rowIndex = rowsArray.findIndex(row => row.contains(event.target));
  const columns = Array.from(rowsArray[rowIndex].querySelectorAll('td'));
  const columnIndex = columns.findIndex(column => column == event.target);
  const r = rowIndex;
  const c = columnIndex;
  console.log(r, c);
  // 根据当前模式调用对应方法
  switch(currentMode) {
    case 'src':
      AssingSrc(r, c);
      break;
    case 'des':
      AssingDes(r, c);
      break;
    case 'wall':
      INITWALLS(r, c);
      break;
  }
  console.log(G);
})

// 按钮点击事件仅修改当前操作模式
document.getElementById("PUTSOURCE").addEventListener("click", () => {
  console.log("ASSING SOURCE CALLED");
  currentMode = 'src';
});
document.getElementById("PUTWALL").addEventListener("click", () => {
  console.log("ASSIGN WALLS CALLED");
  currentMode = 'wall';
});
document.getElementById("PUTDESTINATION").addEventListener("click", () => {
  console.log("ASSIGN DES CALLED");
  currentMode = 'des';
});

如果需要限制起点/终点只能放置1次,只需要在AssingSrc/AssingDes函数内增加已存在判断,放置完成后把currentMode设为null即可;放置墙的场景可以保持currentMode为wall,就能支持连续点击放置多个墙。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.11 22:36:00