首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >事件触发多次

事件触发多次
EN

Stack Overflow用户
提问于 2021-02-22 23:00:35
回答 1查看 433关注 0票数 2

我有一个小问题,我在下面的代码片段中复制了这个问题(以尽可能简单的方式,但它仍然显示了我所面临的问题)。

下面是片段:

代码语言:javascript
复制
const searchBar = document.getElementById('search');
const resBox = document.getElementById('results');

searchBar.addEventListener('input', function handler(e) {
    if (e.target.value === '') {
        resBox.innerHTML = '';
        return false;
    }
  
    setTimeout(() => populate(e), 300);
});

function populate(e) {  
    const btnBox = document.createElement('div');
  
    for (let i = 1; i <= 3; i++) {
        const btn = document.createElement('button');
        btn.classList.add('js-click')
        btn.innerText = 'Click me';
   
        btnBox.appendChild(btn);
    }
  
    resBox.appendChild(btnBox);
  
    dynamicBtnClickListener();
}


function dynamicBtnClickListener() {
    resBox.addEventListener('click', function handler(e) {
        console.log('You clicked me !');
    });
  
  // THE SOLUTION I FOUND FOR THE MOMENT :
  
  //const btns = document.querySelectorAll('button.js-click');
  //btns.forEach(btn => {
  //    btn.addEventListener('click', function handler(e) {
  //        console.log('You clicked me !');
  //    });
  //});
}
代码语言:javascript
复制
<input type="text" id="search">
<div id="results"></div>

正如您在代码段中所看到的,我在输入上有第一个监听器,它在输入时生成一个按钮列表。当它是空的时候,按钮就会消失。在我的实际案例中,它是一个搜索输入,当用户输入它时,它调用一个函数,该函数用DB的结果填充它下面的结果框。

然后,我在按钮上有一个单击监听器。在代码片段中,我只需在单击按钮时放置一个控制台(“您单击了我”)。在我的实际应用程序中,它接受结果项(每个结果都是用户)并将其插入到表中。

打开、关闭、然后重新打开结果框时会出现问题。这是通过输入一些东西,清除输入,然后再输入一些东西来完成的.当您这样做,然后单击其中一个按钮时,它会在打开/关闭结果框时对其触发单击事件多次,因此您将在控制台上多次看到“您单击了我”。

我做了一些研究,其中大多数都要求使用event.stopPropagation()和/或删除事件侦听器。我确实尝试了所有这些可能的解决方案,以我所能想到的每一种方式,但我无法使它发挥作用。

不管怎样,我找到了一种解决这个问题的方法( dynamicBtnClickListener()函数的注释部分),但我觉得这不是最优的。它包括使用querySelectorAll()获取所有按钮,然后循环它们并将单击侦听器添加到每个按钮中,但我认为这不是最佳的,也不是最好的实践。这就是为什么我来这里询问是否有更好的解决方案,可能是保持结果框上的单击侦听器的解决方案(如果这是最理想的解决方案)。顺便问一下,是吗?

所以,即使我找到了解决这个问题的方法,能不能有人告诉我什么是最好的做法和最佳的方法?

非常感谢你的帮助

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-02-22 23:12:50

每次输入文本区域时,每次都访问resBox,而实际元素resBox每次都会获得一个新的事件侦听器(按钮本身没有任何特定的侦听器,因此我让每个按钮都有一个特定的侦听器)。

代码语言:javascript
复制
const searchBar = document.getElementById('search');
const resBox = document.getElementById('results');

searchBar.addEventListener('input', function handler(e) {
    if (e.target.value === '') {
    resBox.innerHTML = '';
    return false;
  }
  
    setTimeout(() => populate(e), 300);
});

function populate(e) {  
  const btnBox = document.createElement('div');
  
  for (let i = 1; i <= 3; i++) {
    const btn = document.createElement('button');
    btn.classList.add('js-click')
    btn.innerText = 'Click me';
    btn.addEventListener('click',function(ev){console.log('You clicked me !')})
    btnBox.appendChild(btn);
  }
  
  resBox.appendChild(btnBox);
}
代码语言:javascript
复制
<input type="text" id="search">
<div id="results"></div>

现在,下面是一个示例,它只有一个事件侦听器,但是可以完全处理情况>:D

从技术上讲,这应该更快(因为一个事件侦听器与许多事件侦听器相比),但是个人我更喜欢这个选项,因为它“感觉更好”,因为一个函数控制了整个按钮布局(这会使它不那么“僵硬”)

PS:速度差太小了,你可以选择(但如果一整吨的按钮,是这样变得更好)

代码语言:javascript
复制
const searchBar = document.getElementById('search');
const resBox = document.getElementById('results');
const randChars=()=>{ //random characters to prove ONE event listener can work for multiple buttons in resBox
  let arr=["a","b","c","d","e"]
  let randIndex=()=>Math.floor(Math.random()*arr.length)||1
  let n=randIndex(); let returnChar=""
  for(let i=0;i<n;i++){returnChar+=arr[randIndex()]}
  return returnChar
}

searchBar.addEventListener('input', function handler(e) {
    if (e.target.value === '') {
    resBox.innerHTML = '';
    return false;
  }
  
    setTimeout(() => populate(e), 300);
});

resBox.addEventListener('click',function(ev){ //single event listener for all buttons
  let currentButton=ev.path[0]
  if(currentButton.tagName!="BUTTON"){return;} //if a button was not clicked
  console.log("Button with text\n'"+currentButton.innerText+"'\nwas clicked")
})

function populate(e) {  
  const btnBox = document.createElement('div');
  
  for (let i = 1; i <= 3; i++) {
    const btn = document.createElement('button');
    btn.classList.add('js-click')
    btn.innerText = 'Click me '+randChars();
    btnBox.appendChild(btn);
  }
  
  resBox.appendChild(btnBox);
}
代码语言:javascript
复制
<input type="text" id="search">
<div id="results"></div>

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66324679

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档