简体   繁体   中英

Why two event listeners are triggered instead of one?

I have element which has two event listeners that are triggered depending of his class name. During click event, his className is changing, and this another class has its own different event listener. Two events should be triggered alternately by every click.

During first click listener calls function editClub, but all the next clicks calls two functions. I don't know why that removed-class-event is triggered. Maybe its because after each event function callListeners is executed, and there are multiple listeners on one object? But should be triggered just one. Later I wrote removeListeners function which remove all existing listeners and put her to call just before callListeners function. But then just editClub function is executed by every click. What's wrong with my code?

function callListeners() 
{
    if ( document.getElementsByClassName('editBtn') )
    {
        let x = document.getElementsByClassName('editBtn');
        for ( let i = 0; i < x.length; i++ )
        {
            x[i].addEventListener('click', editClub);
        }
    }

    if ( document.getElementsByClassName('saveBtn') )
    {
        let x = document.getElementsByClassName('saveBtn');
        for ( let i = 0; i < x.length; i++ )
        {
            x[i].addEventListener('click', saveClub);
        }
    }
}

function editClub(event) 
{
    event.preventDefault();
    this.setAttribute('src','img/\icon_save.png');
    this.setAttribute('class','saveBtn');
    //removeListeners();           <-- here I placed removeListeners function
    callListeners();
}

function saveClub(event) 
{
    event.preventDefault();
    this.setAttribute('src', 'img/\icon_edit.png');
    this.setAttribute('class', 'editBtn');
     //removeListeners();              <-- here I placed removeListeners function
    callListeners();
}

似乎在单击事件发生时您没有删除这些类,因此在第一次单击后,该元素将同时具有两个类。

Just changing an element's class does not change the event listeners that were setup on it previously. They will still be there unless you explicitly remove them, or the elements themselves are destroyed. And you get multiple calls because you keep adding new listeners without removing the old ones.

You could on each click remove the old listener and add the new listener

function editClub(){
  this.removeEventListener("click",editClub);
  this.addEventListener("click",saveClub);
}
function saveClub(){
  this.removeEventListener("click",saveClub);
  this.addEventListener("click",editClub);
}

But that is a bit tedious. Instead you can setup a delegated event listener on a static parent like document . Doing so allows for a single event listener which will be called when either button is clicked. Then in that listener you can check the element's class, and execute the appropriate function for it:

function clubAction(event){
  //get a reference to the element clicked
  var element = event.target;

  //call the appropriate function
  //or just do the work here
  if(element.classList.contains("editClub")){
    editClub.call(element,event);
  } else if(element.classList.contains("saveClub")) {
    saveClub.call(element,event);
  }
}

document.addEventListener("click",clubAction);

classList is a property that lets you get,set,remove, and other operations for the classes of the element.


Demo

 function clubAction(event) { var element = event.target; if (element.classList.contains("editClub")) { editClub.call(element,event); } else if (element.classList.contains("saveClub")) { saveClub.call(element,event); } } document.addEventListener("click", clubAction); function editClub(event) { event.preventDefault(); this.classList.remove('editClub'); this.classList.add('saveClub'); this.innerText = "Save"; } function saveClub(event) { event.preventDefault(); this.classList.add('editClub'); this.classList.remove('saveClub'); this.innerText = "Edit"; } 
 .saveClub { background:#0F0; } .editClub { background:#FF0; } 
 <button class="saveClub">Save</button> <button class="editClub">Edit</button> 

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