首页 > 解决方案 > 数组中的项目神秘消失

问题描述

所以我目前正在做一个卡路里计数器项目,该项目包括让用户首先选择添加具有相应名称和卡路里数量的项目,删除项目或在单击项目旁边的编辑图标时更新它们,最后一次删除所有项目。

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>

标签: javascriptarrays

解决方案


每次用户单击编辑铅笔时,您似乎都会向删除按钮添加一个 eventListener。你永远不会删除这些事件监听器。所以当第一次编辑完成时,有一个删除事件和一个项目被删除。下一次用户单击编辑按钮时,第二个事件被添加到同一个 html 元素,因此两个项目被删除(两个事件将一个接一个地触发)。当您的硬编码列表包含 10 个项目时,这一点变得很明显,您会看到 1、2、3,最后 4 个项目消失。我建议您考虑重置/删除事件监听器。


推荐阅读