我在做一个待办清单应用,尝试往清单中添加待办事项时,总是会重复出现
嗨,我是一名刚入门的编程新手,正在尝试构建The Odin Project的待办清单。这个项目的代码让我卡了两天,这是我第一次在论坛上求助,请你们如果我有错误或者你们不理解我的问题,请务必告诉我。这个代码确实使用了模块,逻辑与显示分离,想把所有东西塞进一个视图里有点困难,所以我把相关的部分放在这里。在我的代码里有一个“添加项目”按钮,用户点击后会生成一个表单,填写后就可以创建一个新项目。这个新项目位于一个div里,用户可以生成任意数量的项目,这个div在我的代码里叫做overview。我想点击每个单独的项目(我为每个项目设置了一个名为data-id的属性,其值与该项目的ID相同),并会显示一个“添加任务”按钮,点击后你可以填写以添加任务,但问题是如果我添加4 个项目,每个项目中的任务都会被重复4 次,我知道这是因为forEach循环,但我尝试把代码放在forEach循环之外生成,或放到另一个变量中都会让我的代码出错。
下面是我的代码的GitHub链接 https://github.com/Oyin414/to_do_list
class ListItems {
constructor( title, priority, dues, info, id ) {
this.title = title
this.priority = priority
this.due = format( new Date(), dues )
this.info = info
this.id = id
}
}
class Project {
constructor( title,id ) {
this.title = title
this.id = id
this.list = []
}
addListItem( item ) {
this.list.push( item )
console.log( this.list )
}
findListItem( id ) {
const result = this.list.filter( item => item.id === id )
return result
}
removeListItem( item ) {
let newList = this.list.filter( value => value.id !== item.id )
this.list = newList
}
}
projectBtn.addEventListener( "click", function() {
event.preventDefault();
let projectName = document.getElementById( "project" ).value
let id = crypto.randomUUID()
const newProject = new Project( projectName,id )
makeProject( projectName,id )
addProject( newProject )
console.log( id )
console.log( getProject() )
project = getProject()
let overview = document.querySelectorAll( ".overview" )
overview.forEach(item=> item.addEventListener( "click",function() {
document.querySelector( '.hide' ).style.display = "block";
let dataId = item.getAttribute( "data-id" )
result = findProject( dataId )
changeProject( result.title )
}))
taskBtn.addEventListener( "click",function () {
event.preventDefault();
let name = document.getElementById( "task" ).value
let priority = document.getElementById( "priority" ).value
let date = document.getElementById( "date" ).value
let taskId = crypto.randomUUID()
let info = document.getElementById( "info" ).value
let task = new ListItems( name, priority, date, info, taskId )
makeTask(name,date,taskId)
})
})
解决方案
确实如此,你会将所有元素加载后逐个循环,并把事件监听器加到它们的每一个上面,因此如果你创建了n 个项目,第一项就会有n 个监听器,而你真正需要的只有一个。一个解决办法是给已经初始化的项目打上一个标记类,我把它叫做 initialized:
for (let item of document.querySelectorAll(".overview:not(.initialized)")) {
item.addEventListener("click", function() {
document.querySelector('.hide').style.display = "block";
let dataId = item.getAttribute("data-id");
let result = findProject(dataId);
changeProject(result.title);
});
item.classList.add("initialized");
}
于是,我们遍历尚未初始化的项,添加监听器并添加 initialized 类。
概念验证:
let index = 1;
document.getElementById("add-overview").addEventListener("click", function() {
let div = document.createElement("div");
div.className = "overview";
div.innerText = index++;
document.getElementById("container").appendChild(div);
for (let item of document.querySelectorAll(".overview:not(.initialized)")) {
item.addEventListener("click", function() {
document.getElementById("result").innerText = item.innerText;
console.log("Click on " + item.innerText + " fired");
});
item.classList.add("initialized");
}
});
#result, .overview {
border: 1px solid red;
font-size: 32pt;
display: inline;
}
<div id="result">Empty</div>
<hr>
<div id="container">
</div>
<input type="button" value="add" id="add-overview">
如上所示,你可以在页面上动态创建任意数量的overview,并点击它们在一个容器中查看,同时在控制台你可以看到事件发生的时间,并验证监听器对任意一个项只会触发一次,即使自那以后创建了新项。
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。