简体   繁体   中英

Call method onclick with addEventListener

I'm trying to make a simple function that will increase a counter when a click occurs on one of my lis. When I run this, I get an error addEventListener is not a function.

HTML:

  <ul class="boxes">
    <li class="box"></li>
    <li class="box"></li>
    <li class="box"></li>
    <li class="box"></li>
    <li class="box"></li>
    <li class="box"></li>
    <li class="box"></li>
    <li class="box"></li>
    <li class="box"></li>
  </ul>

JS:

     var squares = document.getElementsByClassName('box');

   function MyCounter(el){
            this.turn = 0;

              this.addClick = function() {
                this.turn ++;
                console.log(this.turn);
            };

              el.addEventListener('click', this.addClick(), false);
       }
    var c = new MyCounter(squares);

Any suggestions?

getElementsByClassName returns an array-like of elements, not a single element.

It should be:

var squares = document.getElementsByClassName('box')[index];

For each class element loop :

document.querySelectorAll('.box').forEach((e) => {
  ...
  e.addEventListener(...)
});

  function MyCounter(els){ this.turn = 0; this.addClick = function() { this.turn++; console.log(this.turn); }; // old code: //el.addEventListener('click', this.addClick(), false); // 1. parameter el is a collection of DOM elements, not a single element // 2. this.addClick() - calls addClick, resulting in undefined to be passed to addEventListener // 3. context inside addClick (if its reference is passed to addEventListener) would be DOM element, not instance of MyCounter for (var i = 0; i < els.length; i++) { els[i].addEventListener('click', this.addClick.bind(this), false); } } var squares = document.getElementsByClassName('box'); var c = new MyCounter(squares); 
 div.box { display:block; width:100px; height:100px; margin-right:10px; margin-bottom:10px; background: green; } 
 <div class="box">A</div> <div class="box">B</div> 

The problem is you are trying to add an event listener to a list of elements. Instead you need to loop though them and apply the listener to each single one:

function MyCounter(links) {
    var turn = 0;

    function addClick = function() {
        turn ++;
        console.log(turn);
    };

    for (var i=0; i<links.length; i++) {
        links[i].addEventListener('click', addClick(), false);
    }
}

This way you have one function that acts as a global counter.

 function MyCounter(squares){ this.turn = 0; this.addClick = function() { this.turn ++; console.log(this.turn); }; var that = this; for(var i = 0; i < squares.length; i++){ squares[i].addEventListener('click', function(){ that.addClick(); }, false); } } var squares = document.getElementsByClassName('box'); var c = new MyCounter(squares); 
 <ul class="boxes"> <li class="box">box</li> <li class="box">box</li> <li class="box">box</li> <li class="box">box</li> <li class="box">box</li> <li class="box">box</li> <li class="box">box</li> <li class="box">box</li> <li class="box">box</li> </ul> 

You can always use this method, if the boxes are filling the size of the ul element (instead of creating several listeners)

<ul id="boxes" class="boxes">
        <li class="box"></li>
        <li class="box"></li>
        <li class="box"></li>
        <li class="box"></li>
        <li class="box"></li>
        <li class="box"></li>
        <li class="box"></li>
        <li class="box"></li>
        <li class="box"></li>
      </ul>

    <script>


var squares = document.getElementById("boxes");
squares.addEventListener('click', function (el) {
    if ("HTMLLIElement" === el.target.constructor.name) {
        //counter++
    }
}, true);
    </script>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM