为什么触发两个事件侦听器而不是一个?

时间:2018-10-02 20:10:09

标签: javascript dom-events

我有一个元素,该元素具有两个根据其类名触发的事件侦听器。在click事件期间,他的className正在更改,而另一个类具有其自己的不同事件侦听器。每次点击应交替触发两个事件。

在第一次单击侦听器期间,调用函数editClub,但是所有接下来的单击均调用两个函数。我不知道为什么触发了删除类事件。也许是因为在执行每个事件函数callListeners之后,并且在一个对象上有多个侦听器?但是应该只触发一个。后来,我编写了removeListeners函数,该函数删除了所有现有的侦听器,并将其放在callListeners函数之前进行调用。但是,每次单击都只执行editClub函数。我的代码有什么问题?

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();
}

2 个答案:

答案 0 :(得分:0)

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

答案 1 :(得分:0)

仅更改元素的类不会更改之前在其上设置的事件侦听器。除非您明确将它们删除,否则元素本身将被销毁。您会收到多个电话,因为您一直在添加新的侦听器而不删除旧的侦听器。

您可以在每次单击时删除旧的侦听器并添加新的侦听器

("John1").toUpperCase()

但这有点乏味。相反,您可以在像function editClub(){ this.removeEventListener("click",editClub); this.addEventListener("click",saveClub); } function saveClub(){ this.removeEventListener("click",saveClub); this.addEventListener("click",editClub); } 这样的静态父对象上设置delegated event listener。这样做允许一个事件监听器,当单击任一按钮时将调用该事件监听器。然后,在该侦听器中,您可以检查元素的类,并为其执行适当的功能:

document

classList是一个属性,可让您对元素的类进行获取,设置,删除和其他操作。


演示

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