【问题标题】:JavaScript classes and EventListenersJavaScript 类和事件监听器
【发布时间】:2020-05-23 21:50:13
【问题描述】:

我正在尝试将 JavaScript 类架构与 addEventListener 结合使用,这样我就可以一次定义一系列类方法,这些方法将应用于所有适当的 HTML 和/或 CSS 对象。下面是一个只有一个圆圈的示例,单击时应切换红色或蓝色。不幸的是,类确实架构无法与 DOM 正确通信。

我选择内联编写脚本只是为了更轻松地探索基本概念,而不是为了问题的凝聚力而在多个文件中杂耍(我确实意识到,实际上,我可能会使用单独的 HTML 和 JS文件。)

我想按原样进行编码,以便在单击时使圆圈改变颜色。 (另外,没有使用类架构时的代码DID功能。如果有用我可以补充。)

<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
.circle {
  height: 50px;
  width: 50px;
  background-color: #555;
  border-radius: 50%;
}
</style>
</head>
<body>

<h2>Circle CSS</h2>
<div class="circle"></div>
<script>

class GameObject{
  constructor(shape){
    this.shape = shape;
    this.clicks = 0;
  };
  clickEvent(){
    this.shape.addEventListener('click',function(){
      this.clicks += 1
      if (this.clicks % 2 == 1){
        this.shape.style.backgroundColor = 'red';
      }else{
        this.shape.style.backgroundColor = 'blue';
      }
    })
  };
};

let shape = document.querySelector('.circle')
let s = new GameObject(shape);

console.log(s);
</script>

</body>
</html>

此外,以下问题/答案在我脑海中浮现,尽管它们是相关的: Javascript Class & EventListener Dealing with Scope in Object methods containing 'this' keyword called by Event Listeners

编辑:我听取了评论的建议并将clickEvent() 添加到此构造函数中。但是,触发了以下错误:

Uncaught TypeError: Cannot read property 'style' of undefined
    at HTMLDivElement.<anonymous> (circle.html:31)

【问题讨论】:

  • 你永远不会调用 clickEvent 方法,所以事件监听器永远不会触发。尝试在构造函数中调用该方法。
  • this 不是sGameObject 实例;它是元素。见stackoverflow.com/questions/20279484/…

标签: javascript class dom-events


【解决方案1】:

<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
.circle {
  height: 50px;
  width: 50px;
  background-color: #555;
  border-radius: 50%;
}
</style>
</head>
<body>

<h2>Circle CSS</h2>
<div class="circle"></div>
<script>

class GameObject{
  constructor(shape){
    this.shape = shape;
    this.clicks = 0;
    this.clickEvent(); // call the method to add the listener
  };
  clickEvent(){
    this.shape.addEventListener('click',function(){
      this.clicks += 1
      if (this.clicks % 2 == 1){
        this.shape.style.backgroundColor = 'red';
      }else{
        this.shape.style.backgroundColor = 'blue';
      }
    }.bind(this)) // bind callback function to the the correct 'this' context
  };
};

let shape = document.querySelector('.circle')
let s = new GameObject(shape);

console.log(s);
</script>

</body>
</html>

【讨论】:

    【解决方案2】:
    1. 你永远不会调用函数clickEvent
    2. addEventListener 的处理程序使用自己的上下文,要解决这个问题,您可以声明一个变量let that = this,然后在处理程序内部使用它,或者您可以使用箭头函数来使用正确的上下文( GameObject 的实例)。

    这种方法使用箭头函数

    <html>
    <head>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <style>
    .circle {
      height: 50px;
      width: 50px;
      background-color: #555;
      border-radius: 50%;
    }
    </style>
    </head>
    <body>
    
    <h2>Circle CSS</h2>
    <div class="circle"></div>
    <script>
    
    class GameObject{
      constructor(shape){
        this.shape = shape;
        this.clicks = 0;
      };
      clickEvent(){
        this.shape.addEventListener('click',() => {
          this.clicks += 1
          if (this.clicks % 2 == 1){
            this.shape.style.backgroundColor = 'red';
          }else{
            this.shape.style.backgroundColor = 'blue';
          }
        })
      };
    };
    
    let shape = document.querySelector('.circle')
    let s = new GameObject(shape);
    s.clickEvent();
    
    console.log(s);
    </script>
    
    </body>
    </html>

    【讨论】:

    • 我们正朝着正确的方向前进!但是,circle.html:30 Uncaught TypeError: Cannot read property 'style' of undefined at HTMLDivElement.&lt;anonymous&gt; (circle.html:30)
    【解决方案3】:

    将名称clickEvent 更改为handleEvent,并将.addEventListener 调用移到课堂外。

    然后将您的 GameObject 实例作为事件处理程序传递,而不是函数,它会起作用。

    您不需要以这种方式将元素传递给构造函数。它可以从handleEvent 方法上定义的event 对象获得。

    class GameObject {
      constructor() {
        this.clicks = 0;
      };
    
      // Implement the EventListener interface
      handleEvent(event) {
        const shape = event.currentTarget;
        this.clicks += 1
    
        shape.style.backgroundColor = this.clicks % 2 == 1 ? 'red' : 'blue';
    
        console.log(this); // `this` is your class instance
      };
    };
    
    let g = new GameObject();
    
    document.querySelector('.circle')
            .addEventListener("click", g); // use the object as the handler
    
    console.log(g);
    .circle {
      height: 50px;
      width: 50px;
      background-color: #555;
      border-radius: 50%;
    }
    <h2>Circle CSS</h2>
    <div class="circle"></div>

    这里发生的情况是,通过命名方法handleEvent,您将导致您的GameObject 类实现EventListener 接口。因此,该类的 实例 可以用作事件处理程序而不是函数。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-06-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-21
      • 1970-01-01
      • 1970-01-01
      • 2016-08-26
      相关资源
      最近更新 更多