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);
逻辑说明
Grid类专注处理用户交互,在点击时更新游戏数据,并通过自定义事件将数据传递出去;Info类在初始化阶段就注册事件监听,一旦接收到Grid分发的事件,就调用渲染方法更新页面展示;- 借助
CustomEvent的detail属性,可以灵活传递各类游戏数据,实现类间解耦的信息交互。
内容的提问来源于stack exchange,提问作者Rig Raizon
相关产品推荐
相关产品推荐

