【问题标题】:how to avoid localStorage from rendering from the beginning如何避免 localStorage 从一开始就渲染
【发布时间】:2021-04-05 04:03:25
【问题描述】:

代码

以下是当用户点击“添加到购物车”按钮时触发的函数代码。它使用 localStorage 中关于用户从菜单中选择的项目的数据在购物车内创建一行。

function addItemToCart() {
  
  var cartRow = document.createElement("div");
  cartRow.classList.add("cart-row");
  var cartItems = document.getElementsByClassName("cart-items")[0]; //<div class="cart-items">
  var cartItemNames = cartItems.getElementsByClassName("cart-item-title");
  //Putting the data
  var locStore = JSON.parse(localStorage.getItem("selectedProduct"));
  var cartRowContents = locStore.map((item) => {
    return `
        <div class="cart-item cart-column">
            <img class="cart-item-image" src="${item.image}" width="100" height="100">
            <span class="cart-item-title">${item.title}</span>
            <span class="cart-item-size">"Rs.${item.sizePrice}"</span>
        </div>
        <span class="cart-price cart-column">${item.price}</span>
        <div class="cart-quantity cart-column">
            <input class="cart-quantity-input" type="number" value="1">
            <button class="btn btn-danger" type="button">REMOVE</button>
        </div>`;
  });
  cartRowContents = cartRowContents.join("");

  cartRow.innerHTML = cartRowContents;
  cartItems.append(cartRow);
  cartRow
    .getElementsByClassName("btn-danger")[0]
    .addEventListener("click", removeCartItem);
  cartRow
    .getElementsByClassName("cart-quantity-input")[0]
    .addEventListener("change", quantityChanged);
}

问题

每当用户单击“添加到购物车”时,该项目就会存储在 localStorage 中。
现在,假设我的 localStorage 中有一个项目,如下所示:-

[{"productID":"1","image":"http://127.0.0.1:5500/Images/pizza.png","price":300,"title":"Tandoori Pizza","sizePrice":"100","quantity":1}]

使用上述数据,我在购物车中创建了一行。到这里为止,一切正常。
现在,我在 localStorage 中添加了另一个项目,现在 localStorage 看起来像这样:-

[{"productID":"1","image":"http://127.0.0.1:5500/Images/pizza.png","price":300,"title":"Tandoori Pizza","sizePrice":"100","quantity":1},
{"productID":"2","image":"http://127.0.0.1:5500/Images/pizza.png","price":350,"title":"Veggie Supreme","sizePrice":"100","quantity":1}]"

现在,addItemToCart() 再次被触发,因为我们选择了另一个项目。这一次,它将在一行中显示两个项目,因为它也在考虑 localStorage 中实际上已经考虑过的第一个项目。
我应该怎么做才能避免这个问题?

输出 - 用户界面(购物车)

【问题讨论】:

  • 只需检查具有产品 ID 的项目是否已存在并跳过。
  • 是的,“Tandoori Pizza”是 localStorage 中的第一个对象,因此一旦我单击“添加到购物车”按钮,它就会立即添加到购物车中,然后我将“Veggie Supreme”添加到我的购物车中。当我现在单击“添加到按钮”时,它会考虑 localStorage 中已经存在的“Tandoori Pizza”,并将其与购物车中的“Veggie Supreme”一起显示。

标签: javascript


【解决方案1】:

应该这样做(请注意,如果没有整个上下文,我无法对其进行测试):

function addItemToCart(item) {
  
  var cartRow = document.createElement("div");
  cartRow.classList.add("cart-row");
  var cartItems = document.getElementsByClassName("cart-items")[0]; //<div class="cart-items">
  var cartItemNames = cartItems.getElementsByClassName("cart-item-title");
  //Putting the data
  var cartRowContents = `
        <div class="cart-item cart-column">
            <img class="cart-item-image" src="${item.image}" width="100" height="100">
            <span class="cart-item-title">${item.title}</span>
            <span class="cart-item-size">"Rs.${item.sizePrice}"</span>
        </div>
        <span class="cart-price cart-column">${item.price}</span>
        <div class="cart-quantity cart-column">
            <input class="cart-quantity-input" type="number" value="1">
            <button class="btn btn-danger" type="button">REMOVE</button>
        </div>`;
  cartRowContents = cartRowContents.join("");

  cartRow.innerHTML = cartRowContents;
  cartItems.append(cartRow);
  cartRow
    .getElementsByClassName("btn-danger")[0]
    .addEventListener("click", removeCartItem);
  cartRow
    .getElementsByClassName("cart-quantity-input")[0]
    .addEventListener("change", quantityChanged);
}

/**
 * Render all the items in cart, 
 * call this instead of addItemToCart after an item was added to local storage.
 **/
function renderItemsInCart() {
  var cartItems = document.getElementsByClassName("cart-items")[0]; //<div class="cart-items">
  carItems.innerHTML = "";
  var locStore = JSON.parse(localStorage.getItem("selectedProduct"));
  var cartRowContents = locStore.map((item) => addItemToCart(item));
}

【讨论】:

  • 感谢您的回答,使用您的代码,它会多次显示项目但在不同的行中。早些时候,它在一行中显示 2 个项目。现在,它在不同的行中显示每个项目。
  • 是的,抱歉我忘记清理购物车了,现在就试试吧
  • 显然,我们可以通过保存渲染行列表或在 DOM 中查找它们来做得更好。但是这个解决方案最接近你已经拥有的,所以让我们先尝试一下
  • 现在,它运行良好。非常感谢。
【解决方案2】:

我知道答案已被接受,但假设您的商品有一个 ID,您可以使用它来使每个购物车行唯一(用于更新数量和删除购物车商品)。

PS:我没有对此进行测试。只是为了优化和修复您的 UI 问题

//add cart item row
function addItemToCart () {
    document.getElementsByClassName("cart-items")[0].insertAdjacentHTML(
        'beforeend',
        `<div class="cart-row" id="cartid-${item.id}">
            <div class="cart-item cart-column">
                <img class="cart-item-image" src="${item.image}" width="100" height="100">
                <span class="cart-item-title">${item.title}</span>
                <span class="cart-item-size">"Rs.${item.sizePrice}"</span>
            </div>
            <span class="cart-price cart-column">${item.price}</span>
            <div class="cart-quantity cart-column">
                <input class="cart-quantity-input" type="number" value="1" id="quantityid-${item.id} onchange="quantityChanged">
                <button class="btn btn-danger" type="button" onclick="removeCartItem(this)">REMOVE</button>
            </div>
        </div>`      
    )
}

//remove the cart item row
function removeCartItem (input) {
    input.parentNode.remove()
}


/**
 * Render all the items in cart, 
 * call this instead of addItemToCart after an item was added to local storage.
 **/
function renderItemsInCart() {
  var cartItems = document.getElementsByClassName("cart-items")[0]; //<div class="cart-items">
  carItems.innerHTML = "";
  var locStore = JSON.parse(localStorage.getItem("selectedProduct"));
  var cartRowContents = locStore.map((item) => addItemToCart(item));
}

【讨论】:

  • 是的。后来我意识到我应该在这里使用ID。谢谢你的回答。
【解决方案3】:

为什么不访问locStore 的最后一个元素,因为那将是最新的,对吗?目前,您在整个 localStorage 项目上调用 .map,但我假设 addItemToCart 仅在您的 localStorage 更新为最近的项目之后才被调用,并且您只想要 DOM 来反映最新的变化。我认为以下应该可行:-


 var item = locStore[locStore.length-1];
 var cartRowContents = 
        `<div class="cart-item cart-column">
            <img class="cart-item-image" src="${item.image}" width="100" height="100">
            <span class="cart-item-title">${item.title}</span>
            <span class="cart-item-size">"Rs.${item.sizePrice}"</span>
        </div>
        <span class="cart-price cart-column">${item.price}</span>
        <div class="cart-quantity cart-column">
            <input class="cart-quantity-input" type="number" value="1">
            <button class="btn btn-danger" type="button">REMOVE</button>
        </div>`;

【讨论】:

  • 您的方法似乎不错。会尝试。谢谢。
【解决方案4】:

你可以在函数的请求中清空整个购物车,然后让函数从 LocalStorage 中填充所有内容。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-25
    • 2020-12-21
    • 2019-02-20
    • 1970-01-01
    • 1970-01-01
    • 2021-08-04
    相关资源
    最近更新 更多