javascript - 将事件监听器添加到 foreach 循环中的每个项目
问题描述
I have a node list in a variable
connectedAnalysis = document.querySelectorAll('.connAnalysisUl li')
each li represents some text which I want to be removed when clicked on that li tag.
I have code like this
connectedAnalysis.forEach((item) => {
item.addEventListener('click', (e) => {
e.preventDefault()
console.log(item)
})
})
然后我注意到一些奇怪的行为。如果我的节点列表中有 3 个元素,并且如果我单击第一个元素,我将获得 3 次控制台日志,如果我单击第二个 li,我将获得两次控制台日志。所以在我继续之前,我想了解为什么会发生这种情况以及如何防止这种情况发生。我阅读了很多关于事件传播等的内容,但没有什么能帮助我理解我在这里面临的情况。我想要的是,如果我单击任何项目,它只会被触发一次。
这是完整的代码
//here I'm defining some variables
let connectedAnalysis = document.getElementById('connectedAnalysis')
let getAnalyisisNameDiv = document.getElementById('resultConnectedAnalysis')
let relatedAnalysisParent = document.getElementById('relatedAnalysis')
let parentUl = document.querySelector('.connAnalysisUl')
//here I'm listening for users input and then I query mongoDB collection, I'm displaying all the result as li items
connectedAnalysis.addEventListener('input', (e) => {
if (connectedAnalysis.value.length > 2) {
fetch('/analysis/'+e.target.value).then((data) => {
data.json().then((result) => {
getAnalyisisNameDiv.innerHTML = ''
for(i=0; i<result.length; i++) {
let liItem = document.createElement('li')
liItem.className +="list-group-item"
let link = document.createElement('a')
link.href=result[i]._id
liItem.appendChild(link)
let analysisName = document.createTextNode(result[i].analysisName)
link.appendChild(analysisName)
getAnalyisisNameDiv.appendChild(liItem)
} // for end
//here I would like to take all li tags inside my ul tag and when the user clicks on li item I would like to add it to the DOM
let analysisNameList = document.querySelectorAll('#resultConnectedAnalysis li')
analysisNameList.forEach((item) => {
item.addEventListener('click', (e) => {
e.preventDefault()
// creating hidden input tag and grab analysis id
let connectedAnalysisID = document.createElement('input')
connectedAnalysisID.type = 'hidden'
connectedAnalysisID.name = 'connectedTo[]'
connectedAnalysisID.setAttribute('value', e.srcElement.attributes.href.textContent)
//here I'm creating a remove button
let removeButton = document.createElement('small')
removeButton.className += 'ml-1 float-right removeConnectedAnalysis'
let removeText = document.createTextNode('x')
removeButton.appendChild(removeText)
//here I'm creating li tag and adding everything to the DOM
let connectedAnalysisLi = document.createElement('li')
connectedAnalysisLi.className += 'list-inline-item __connectedAnalysis'
let connectedAnalysisInnerText = document.createTextNode(e.target.innerText)
connectedAnalysisLi.appendChild(connectedAnalysisInnerText)
connectedAnalysisLi.appendChild(removeButton)
connectedAnalysisLi.appendChild(connectedAnalysisID)
connectedAnalysisLi.appendChild(connAnalysisName)
parentUl.appendChild(connectedAnalysisLi)
relatedAnalysisParent.appendChild(parentUl)
//here I would like to remove item which is added by the user
let removeConnectedAnalysis = document.querySelectorAll('.connAnalysisUl li')
removeConnectedAnalysis.forEach((item) => {
item.addEventListener('click', (e) => {
e.preventDefault()
item.remove()
})
})
})// addeventlistener end
})// analysisNameList end
})// datajson end
})// fetch end
} else {
getAnalyisisNameDiv.innerHTML = ''
}
})// connectedAnalysis event listener end
我相信我迷失在循环和范围以及我正在尝试学习的其他一些东西中。如果您能帮助我更好地理解我的错误,我将非常感激。谢谢
解决方案
最好使用事件委托,在所有元素的祖先中设置一个事件处理程序,这些元素可以触发事件并允许事件冒泡到该祖先。然后,在单个事件处理程序中,检查哪个元素触发了事件(如果需要)并采取行动。
这是您所说的尝试做的一个示例:
// Get a reference to the ancestor
let parent = document.querySelector(".parent");
// Set up a click event on the ancestor
parent.addEventListener("click", function(event){
// Remove the element that triggered the event in the first place
parent.removeChild(event.target);
});
<ul class="parent">
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
<li>Item 5</li>
<li>Item 6</li>
<li>Item 7</li>
<li>Item 8</li>
</ul>
推荐阅读
- java - 将嵌套地图转换为嵌套列表
- android - Xml - 带线条的背景
- spring-boot - 使用 JDK 14 的 spring boot 应用程序无法启动。也没有错误
- floating-point - 可以在 Julia 中使用 Float64 表示的最大正整数
- caching - 云端缓存策略中查询参数的格式是什么
- postgresql - 如何使用 SQLAlchemy / Python 推迟缓慢的数据库操作
- mysql - 获取地址列表没有英国地址 mysql
- java - 在firebase android中读取随机生成的孩子的值
- google-sheets - 基于表单响应的 Google 电子表格格式
- laravel - 想要使用 PHPUnit 在 laravel 中对 slack 通知进行单元测试