javascript - 数组中的项目神秘消失
问题描述
所以我目前正在做一个卡路里计数器项目,该项目包括让用户首先选择添加具有相应名称和卡路里数量的项目,删除项目或在单击项目旁边的编辑图标时更新它们,最后一次删除所有项目。
UI基本上会显示用户添加的所有项目(包括名称和卡路里数量),其中每个项目旁边都会有一个编辑图标,如果单击该图标,它会给用户选项编辑和删除它们。
我还没有进入编辑部分,因为我目前被困在删除部分。
假设我在列表中有 3 个项目,当我单击编辑按钮然后删除时,一切正常,html 元素被删除并且看起来不错。如果我再重复一次该过程,它仍然有效,但是当我最后一次重复该过程时,问题就发生了。
出于某种原因,当我点击编辑按钮时没有任何反应,我已经检查过了,显然项目数组是完全空的,即使我只删除了 3 个项目中的 2 个。
我已经尝试了所有方法,但我已经完全卡住了 3 天。
// Item Controller
const ItemController = function() {
// Hard coded items
data = [{
name: "Hamburguer",
id: 0,
calories: 1000
},
{
name: "Pasta",
id: 1,
calories: 700
},
{
name: "Apple",
id: 2,
calories: 70
}
]
return {
getItems: function() {
return data;
},
deleteAllItems: function() {
data.items = [];
UIController().clearItems();
},
getTotalCalories: function() {
totalCalories = 0;
this.getItems().forEach(item => {
totalCalories += parseInt(item.calories)
});
UIController().changeToTotalCalories(totalCalories);
},
removeSingleItem: function(item, li) {
// Getting the index of the item
indexItem = items.getItems().indexOf(item);
// Deleting item from array
items.getItems().splice(indexItem, 1);
// Deleting li item from UI
li.remove();
console.log(items.getItems());
}
}
};
const items = ItemController();
// UI controller
const UIController = function() {
return {
displayItems: function(itemsPresented) {
itemsPresented.forEach(function(item) {
itemList = document.getElementById("item-list");
itemList.innerHTML += `
<li class="collection-item" id="${item.id}">
<strong>${item.name}: </strong><em>${item.calories} calories</em>
<a href="#" class="secondary-content">
<i class="edit-item fa fa-pencil">
</i>
</a>
</li>
`;
})
},
clearItems: function() {
itemList = document.getElementById("item-list");
itemList.innerHTML = "";
items.getTotalCalories();
},
changeToTotalCalories: function(totalCalories) {
document.querySelector(".total-calories").textContent = totalCalories;
},
}
}
const uiCtrl = UIController();
// So when the page loads, the hard coded items can be represented
uiCtrl.displayItems(items.getItems());
// To delete all the items at once
clearAllBtn = document.querySelector(".clear-btn");
clearAllBtn.addEventListener("click", (e) => {
items.deleteItems();
e.preventDefault();
})
// Getting the li element (The one that has all the hard-coded items)
itemList = document.getElementById("item-list");
itemList.addEventListener("click", e => {
// Checking if the user is clicking the Edit Icon
if (e.target.classList.contains("edit-item")) {
items.getItems().forEach(item => {
li = e.target.parentElement.parentElement;
// Getting the item that has the edit icon that the user clicked
if (item.id === parseInt(e.target.parentElement.parentElement.id)) {
// Putting the name and the calories of the item that is being edited in the input fields
document.getElementById("item-name").value = item.name;
document.getElementById("item-calories").value = item.calories;
// Changing the buttons so when the user edits an item, they have the options Update and Delete
document.querySelector(".add-btn").style.display = "none";
document.querySelector(".update-btn").style.display = "block";
document.querySelector(".delete-btn").style.display = "block";
document.querySelector(".back-btn").style.display = "none";
// If the user clicks the delete button
document.querySelector(".delete-btn").addEventListener("click", e => {
// Changing all the buttons back to normal
document.querySelector(".add-btn").style.display = "block";
document.querySelector(".update-btn").style.display = "none";
document.querySelector(".delete-btn").style.display = "none";
document.querySelector(".back-btn").style.display = "block";
// Clearing out the input fields
document.getElementById("item-name").value = "";
document.getElementById("item-calories").value = "";
// Deleting item
items.removeSingleItem(item, li);
// Updating the calories
items.getTotalCalories();
e.preventDefault();
});
}
});
}
})
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css">
<link href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" integrity="sha384-wvfXpqpZZVQGK6TAh5PVlGOfQNHSoD2xbE+QkPxCAFlNEevoEH3Sl0sibVcOQVnN" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script>
<nav>
<div class="nav-wrapper blue">
<div class="container">
<a href="#" class="brand-logo center">
Tracalorie
</a>
<ul class="right">
<li>
<a href="#" class="clear-btn btn blue lighten-3">
Clear All
</a>
</li>
</ul>
</div>
</div>
</nav>
<br>
<div class="container">
<!-- Form Card -->
<div class="card">
<div class="card-content">
<span class="card-title">
Add Meal / Food Item
</span>
<form class="col">
<div class="row">
<div class="input-field col s6">
<input type="text" id="item-name" placeholder="Add item">
<label for="item-name">Meal</label>
</div>
<div class="input-field col s6">
<input type="text" id="item-calories" placeholder="Add calories">
<label for="item-calories">Calories</label>
</div>
<button class="add-btn btn blue darken-3"><i class="fa fa-plus"></i>
Add Meal</button>
<button style="display: none;" class="update-btn btn orange" display=><i class="fa fa-pencil-square-o"></i>
Update Meal</button>
<button style="display: none;" class="delete-btn btn red"><i class="fa fa-remove"></i>
Delete Meal</button>
<button class="back-btn btn grey pull-right"><i class="fa fa-chevron-circle-left"></i>
Back</button>
</div>
</form>
</div>
</div>
<!-- Calorie Count -->
<h3 class="center-align">Total Calories: <span class="total-calories">
0
</span></h3>
<!-- Item list -->
<ul id="item-list" class="collection">
</ul>
</div>
解决方案
每次用户单击编辑铅笔时,您似乎都会向删除按钮添加一个 eventListener。你永远不会删除这些事件监听器。所以当第一次编辑完成时,有一个删除事件和一个项目被删除。下一次用户单击编辑按钮时,第二个事件被添加到同一个 html 元素,因此两个项目被删除(两个事件将一个接一个地触发)。当您的硬编码列表包含 10 个项目时,这一点变得很明显,您会看到 1、2、3,最后 4 个项目消失。我建议您考虑重置/删除事件监听器。
推荐阅读
- google-cloud-run - 某些域的基本域映射损坏
- javascript - 为什么我的 Giphy API 的 POST 请求返回状态 400?
- php - 如何在 php 中知道 sql 获取的行何时共享相同的 ID 以及何时开始一组新的 ID
- python - 在 Google Colab Research Notebook 中读取 shell 脚本结果
- geopandas - 将 geopandas 数据框传递给`folium.Choropleth`(地图呈现灰色)
- javascript - 如何使用在构造函数中创建的函数?
- c++ - 除了将其作为参数传递之外,有没有办法在静态函数中获取类对象?
- python - 从我的硬盘打开 csv 文件并导入数据库
- javascript - 温斯顿每日旋转文件 maxSize 不起作用
- java - 如何检查文件是否已完全写入/是否持有仅在 Java 中具有读取访问权限的写锁