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

JavaScript中如何触发自定义事件?跨类事件通信失效问题排查

问题描述

我想用JavaScript实现一个简单游戏,将游戏主体封装为Grid类,游戏信息展示封装为Info类,要求用户每次点击鼠标后更新Info类的信息。

我编写了两个类,简化后的代码如下:

Grid类

class Grid {
  constructor(container) {
    this.container = container;
    this.myEvent = new Event("myCustomEvent")
    this.container.addEventListener('click', () => {
      this.container.addEventListener("myCustomEvent", e => {
        console.log(e)
      })
    })
  }
}

Info类

class Info {
  constructor(grid, container) {
    this.container = container;
    this.grid = grid;
    this.container.dispatchEvent(this.myEvent)
  }
}

实例化代码

const grid = new Grid(document.querySelector(".container"));
const info = new Info(grid, document.querySelector(".container"));

但上述代码没有任何效果。我希望在不合并两个类的前提下,实现一个类中的信息动态传递并显示到另一个类中。

我测试了同一类内触发自定义事件的代码,能正常打印事件:

class Grid {
  constructor(container) {
    this.container = container;
    this.myEvent = new Event("myCustomEvent")
    this.container.addEventListener("myCustomEvent", e => {
      console.log(e)
    })
    this.container.dispatchEvent(this.myEvent)
  }
}
const grid = new Grid(document.querySelector(".container"));

但跨类触发时却无法生效。


问题分析与解决方案

你的代码存在三个核心问题:

  • 事件监听注册时机错误:Grid类中把myCustomEvent的监听逻辑放在了click回调内,只有用户点击后才会注册监听,但Info实例化时就触发了事件,此时监听尚未存在,无法捕获事件。
  • 自定义事件访问错误:Info类中this.myEvent未定义,应该调用Grid实例上的事件对象,即this.grid.myEvent。
  • 事件触发时机错误:需要在用户点击Grid容器时触发自定义事件,而非Info实例化阶段。

修正后的代码

Grid类(处理交互与事件分发)

class Grid {
  constructor(container) {
    this.container = container;
    // 使用CustomEvent以便携带游戏数据
    this.myEvent = new CustomEvent("myCustomEvent", {
      detail: {
        score: 0,
        stepCount: 0
      }
    });

    // 点击容器时更新数据并分发事件
    this.container.addEventListener('click', () => {
      // 模拟游戏数据更新
      this.myEvent.detail.score += 10;
      this.myEvent.detail.stepCount += 1;
      // 向容器分发自定义事件
      this.container.dispatchEvent(this.myEvent);
    });
  }
}

Info类(监听事件与更新展示)

class Info {
  constructor(grid, container) {
    this.container = container;
    this.grid = grid;
    // 初始化时就注册自定义事件监听
    this.container.addEventListener("myCustomEvent", (e) => {
      this.renderInfo(e.detail);
    });
    // 初始化展示默认数据
    this.renderInfo(this.grid.myEvent.detail);
  }

  // 更新信息展示的方法
  renderInfo(data) {
    this.container.innerHTML = `当前得分:${data.score} | 已走步数:${data.stepCount}`;
  }
}

实例化代码

const gameContainer = document.querySelector(".game-container");
const infoContainer = document.querySelector(".info-container");
const grid = new Grid(gameContainer);
const info = new Info(grid, infoContainer);

逻辑说明

  1. Grid类专注处理用户交互,在点击时更新游戏数据,并通过自定义事件将数据传递出去;
  2. Info类在初始化阶段就注册事件监听,一旦接收到Grid分发的事件,就调用渲染方法更新页面展示;
  3. 借助CustomEvent的detail属性,可以灵活传递各类游戏数据,实现类间解耦的信息交互。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 03:47:02