在JavaScript中如何触发自定义事件?

huangapple go评论65阅读模式
英文:

How can I trigger a customEvent in JavaScript?

问题

I am trying to implement a simple game in JavaScript where the game itself is one class and the info about the game is the other. The info must be updated after each time the user clicks the mouse.
我正在尝试在JavaScript中实现一个简单的游戏,其中游戏本身是一个类,游戏信息是另一个类。信息必须在用户每次点击鼠标后更新。

I have two classes. The Grid class is the game itself. This is simplification:
我有两个类。Grid类是游戏本身。这是简化版:

And this is the Info class.
这是Info类。

I then create the instances of the two classes:
然后我创建了这两个类的实例:

However this does nothing. Is there a way to dynamically update and display the information that exists in one class but must be passed to another? I don't want to mix these two classes into one.
然而,这并没有做任何事情。有没有一种方法可以动态更新和显示存在于一个类中的信息,但必须传递到另一个类?我不想将这两个类混合在一起。

I can see that this works. It logs out the event:
我可以看到这个可以工作。它记录了事件:

However not when I dispatch the event in a different class.
但当我在不同的类中分发事件时却没有效果。

英文:

I am trying to implement a simple game in JavaScript where the game itself is one class and the info about the game is the other. The info must be updated after each time the user clicks the mouse.
I have two classes. The Grid class is the game itself. This is simplification:

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

And this is the Info class.

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

I then create the instances of the two classes:

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

However this does nothing. Is there a way to dynamically update and display the information that exists in one class but must be passed to another? I don't want to mix these two classes into one.

I can see that this works. It logs out the event:

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"));

However not when I dispatch the event in a different class.

答案1

得分: 1

You get your code wrong:

class Info {
  constructor(grid, container) {
    this.container = container;
    this.grid = grid;
    this.container.dispatchEvent(this.myEvent) // here it should be grid.myEvent
  }

请注意,如果在点击 grid 容器之前创建 Info 的实例,事件将被分发到无处,什么也不会发生:

const grid = new Grid(document.querySelector(".container"));
// 你需要先点击 grid 容器...
const info = new Info(grid, document.querySelector(".container"));

这涉及到你的第一个 Grid 片段。
第二个将会工作。下次请准备一个可运行的代码片段... 你已经用两个不同版本的 Grid 惯坏了我们。

但我认为你的代码并不完美。你的目标是解耦,但你的 Info 类有 Grid 作为依赖项。你尝试使用事件进行通信,这是一种好的架构。由于某种原因,你试图过于追求 DRY 原则,并设法在一个地方定义你的自定义事件。这不是一个好的做法,只需移除 Grid 的依赖性,然后在 Info 中以不关心任何 Grid 类的方式触发事件:

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

class Info {
  constructor(container) {
    this.container = container;
    this.container.dispatchEvent(new Event('myCustomEvent'))
  }
}
英文:

You get your code wrong:

class Info {
  constructor(grid, container) {
    this.container = container;
    this.grid = grid;
    this.container.dispatchEvent(this.myEvent) // here it should be grid.myEvent
  }

Note that if you create the Info's instance before the clicking on the grid container, you will dispatch the event into nowhere, nothing will happen:

const grid = new Grid(document.querySelector(".container"));
// you need to click the grid container first...
const info = new Info(grid, document.querySelector(".container"));

That was about your first snippet of Grid.
The second one would work. Please prepare a working code snippet next time... You've managed to spoil us with 2 different version of your Grid.

But I think your code isn't perfect. Your goal is decoupling but your Info class has Grid as a dependency. You try to communicate with events and that's a good architecture. For some reason you try DRY too hard and manage to define your custom event in one place. Not a good way to go, just remove the Grid dependency and emit the event in Info agnostically to any Grid class:

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

class Info {
  constructor(container) {
    this.container = container;
    this.container.dispatchEvent(new Event('myCustomEvent'))
  }

huangapple
  • 本文由 发表于 2023年5月15日 06:19:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/76249916.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定