LocalStorage 更新元素导致与 JQuery 中的 JSON 重复

Posted

技术标签:

【中文标题】LocalStorage 更新元素导致与 JQuery 中的 JSON 重复【英文标题】:LocalStorage updating element causes duplication with JSON in JQuery 【发布时间】:2020-06-20 02:59:14 【问题描述】:

所以我试图用 JSON 更新 LocalStorage 中的一个元素,但我不知道我做错了什么。我想添加一个产品,并在再次添加相同的产品时更新其数量。

第一次添加 X 产品时,我在一个元素中得到了正确的数量。添加另一个 X 后,数量变为空。添加一个全新的产品 Y,将导致多个重复的 Y 元素全部为空。

肯定有一些我似乎无法弄清楚的逻辑错误。 addToCart 函数是我怀疑事情出错的地方。非常感谢任何帮助,因为我是 javascript 和 JQuery 的新手。谢谢。

$(document).ready(function() 
  // caching
  let $table = $(".shoe-table");

  fetch("shoes.json")
    .then(resp => resp.json())
    .then(data => 
      let shoes = data.shoes;
      let rows = [1, 2, 3];
      let shoeCard = "";
      let products = JSON.parse(localStorage.products || "[]");
      console.log(products);

      function addToCart(cBtn) 
        let clickedButton = $(cBtn);
        let buttonID = clickedButton.attr("id");
        let thisInput = $("#" + clickedButton.attr("id") + ".input-form").children("input");
        let newShoe = 
          id: buttonID,
          image: shoes[buttonID].image,
          name: shoes[buttonID].name,
          price: shoes[buttonID].price,
          quantity: parseInt(thisInput.val())
        ;

        if (products.length != 0) 
          products.forEach(shoe => 
            if (shoe.name == newShoe.name) 
              shoe.quantity += newShoe.quantity;
              localStorage.setItem("products", JSON.stringify(products));
              console.log(products);
             else 
              products.push(newShoe);
              localStorage.setItem("products", JSON.stringify(products));
            
          );
         else 
          products.push(newShoe);
          localStorage.setItem("products", JSON.stringify(products));
        
      

      let counter = 0;
      rows.forEach(row => 
        shoeCard += "<tr>";
        for (let index = 0; index < 4; index++) 
          shoeCard +=
            "<td class='card text-center'>" +
            "<img class='card-img-top' src=" +
            shoes[counter].image +
            " alt='Card image cap'>" +
            "<h5 class='card-title'>" +
            shoes[counter].name +
            "</h5>" +
            "<p class='card-text'>kr " +
            shoes[counter].price +
            "</p>" +
            "<button id=" +
            counter +
            " class='orderNow btn btn-outline-dark'>ORDER NOW</button>" +
            "<div id=" +
            counter +
            " class='input-form'><input class='qty-chooser' type='number' placeholder='Choose quantity' min=0 max=10>" +
            "<button class='btn-add-to-cart' disabled='disabled'>ADD TO CART</button>" +
            "</div>" +
            "</td>";
          counter++;
        

        shoeCard += "</tr>";
      );

      $table.append(shoeCard);
      let $inputForm = $(".input-form");
      let $orderBtn = $(".orderNow");

      $inputForm.hide();

      let activeButton = -1;

      // Denna metod tittar om man redan har en aktiv beställning
      function isProductActive() 
        let btnID = $(this).attr("id");
        if (activeButton == -1) 
          activeButton = btnID;
          toggleOrder($(this));
         else if (btnID != activeButton) 
          toggleOrder($("#" + activeButton + ".orderNow"));
          toggleOrder($(this));
          activeButton = btnID;
         else if (btnID == activeButton) 
          toggleOrder($(this));
          activeButton = -1;
        
      

      $orderBtn.click(isProductActive);

      function toggleOrder(buttonC) 
        console.log("INSIDE TOGGLE");
        let clickedBtn = $(buttonC);
        let thisInputForm = $("#" + clickedBtn.attr("id") + ".input-form");

        let inputBtn = thisInputForm.children("button");
        let inputIn = thisInputForm.children("input");

        // RESETTAR ELEMENT I .input-form
        function resetInputForm() 
          inputBtn.css("background", "");
          inputBtn.css("color", "");
          inputBtn.attr("disabled", "disabled");
          inputIn.val(null);
        

        // DENNA KNAPP ÄR EN ADD TO CART FUNKTION
        inputBtn.click(function() 
          // TODO: LÄGG TILL LOGIK FÖR ATT LÄGGA TILL VARUKORG
          console.log("INSIDE ADDING");

          addToCart(clickedBtn);
          thisInputForm.hide("slow");
          clickedBtn.text("ORDER NOW");
          clickedBtn.css("background", "");
          resetInputForm();
          activeButton = -1;
        );
        // BEROENDE PÅ QUANTITY REAGERAR ADD TO CART KNAPPEN
        inputIn.change(function() 
          let qty = inputIn.val();

          if (qty >= 1 && qty <= 10) 
            inputBtn.removeAttr("disabled");
            inputBtn.css("background", "rgb(15, 163, 10)");
            inputBtn.css("color", "white");
           else if (qty < 1) 
            resetInputForm();
           else if (qty > 10) 
            inputIn.val(10);
          
        );

        // KONTROLLERAR ORDER NOW KNAPPEN
        if (clickedBtn.text() == "CANCEL") 
          thisInputForm.hide("slow");
          clickedBtn.text("ORDER NOW");
          clickedBtn.css("background", "");
          resetInputForm();
         else 
          thisInputForm.show("slow");
          clickedBtn.text("CANCEL");
          clickedBtn.css("background", "red");
          inputBtn.attr("disabled", "disabled");
          resetInputForm();
        
      
    )
    .catch(err => console.error(err));
);

【问题讨论】:

【参考方案1】:

使用以下代码更改localStorage 代码。问题是您将每次forEach 迭代中的所有产品推送到本地存储。

试试下面的代码。

if (products.length != 0) 
  let isExists = products.some(shoe => shoe.name === newShoe.name);
  if (!isExists) 
    products.push(newShoe);
   else 
      products = products.map(shoe => 
      if (shoe.name == newShoe.name && !isNaN(newShoe.quantity)) 
        shoe.quantity += newShoe.quantity;
        return shoe;
      
      return shoe;
    );
  
  localStorage.setItem("products", JSON.stringify(products));
 else 
  products.push(newShoe);
  localStorage.setItem("products", JSON.stringify(products));


【讨论】:

【参考方案2】:
    if (products.length != 0) 
      for (let index = 0; index < products.length; index++) 
        if (products[index].name == newShoe.name) 
          products[index].quantity += newShoe.quantity;
          localStorage.setItem("products", JSON.stringify(products));    
          break;
         else
          products.push(newShoe);
          localStorage.setItem("products", JSON.stringify(products));  
          break;
        
      
     else 
      products.push(newShoe);
      localStorage.setItem("products", JSON.stringify(products));
    

这解决了重复的问题,但在添加现有产品时仍然存在空数量问题。

【讨论】:

以上是关于LocalStorage 更新元素导致与 JQuery 中的 JSON 重复的主要内容,如果未能解决你的问题,请参考以下文章

XMLHttpRequest 替换元素不适用于 LocalStorage

使用 AJAX 和 PHP 更新表单字段

解决localstorage容量大导致页面加载变慢

web前端巨无霸长文-持续更新2021-10-14(1.6w+字)

从 REST 服务更新 localStorage,但只更新新记录

如何更新 LocalStorage 中持久化的 Redux 状态结构