如何避免在 localstorage 数组上获取重复的元素

How to avoid getting duplicated elements on localstorage array

我有以下代码,每次单击按钮时都会在我的本地存储中的数组上生成一个新元素

let addCartItemButtons = document.getElementsByClassName('product-description-add')
for (let i = 0; i < addCartItemButtons.length; i++){
    let button = addCartItemButtons[i]
    button.addEventListener('click', function(event){
        let buttonClicked = event.target
        let getTitle = buttonClicked.parentElement.parentElement.parentElement.querySelector('.product-title').innerText
        let getImage = buttonClicked.parentElement.parentElement.parentElement.querySelector('.product-header img').src
        let getColor = buttonClicked.parentElement.parentElement.querySelector('.product-description-text li span').innerText
        let getSize = buttonClicked.parentElement.parentElement.querySelector('.product-description-text li select').value
        let getPrice = buttonClicked.parentElement.parentElement.querySelector('.product-description-price').innerText
        let getSpan = buttonClicked.parentElement.parentElement.querySelector('li span').getAttribute('id')
        let oldItems = JSON.parse(localStorage.getItem('newProduct')) || [];
        let newItem = {
            'id': i+1,
            'title': getTitle,
            'image': getImage,
            'color': getColor,
            'size': getSize,
            'price': getPrice,
            'spanid': getSpan,
        };
        let data = JSON.parse(localStorage.getItem('newProduct'))
        if(localStorage.getItem('newProduct') == null) {
            oldItems.push(newItem);
            localStorage.setItem('newProduct', JSON.stringify(oldItems));
        } else {
            if(data.indexOf(newItem) == -1){
                oldItems.push(newItem);
                localStorage.setItem('newProduct', JSON.stringify(oldItems));
            }else{
                alert('element already added')
            }
        }
    })
} 

我的问题是我试图创建一个验证来检查该元素是否已经添加到本地存储,所以在那种情况下应该会出现警报,但它根本不起作用,我'在我第一次添加元素后,我仍然能够将它添加到我的本地存储中。我不知道如何解决这个问题,有什么想法吗? :)

出现问题是因为对象不能仅仅因为它们具有相同的 属性 值而被认为是相等的。

let oldItems = JSON.parse(localStorage.getItem('newProduct')) || [];

oldItems 创建为空数组或新创建的对象数组,其中 属性 值表示之前单击和保存的项目。

let data = JSON.parse(localStorage.getItem('newProduct'))

还将为之前单击的按钮创建一个新对象数组(如果有的话),但不会包含与 oldItems 相同的对象,因为 JSON.parse 每次都创建新对象打电话。

定义 newItem 还会创建一个新对象,它将 不是 oldItemsdata 中的任何条目相同的对象.

为了解决这个问题,您可以为所有项目添加唯一的产品代码,这样您就可以仅根据产品代码搜索以前的数据进行匹配,或者编写一个比较例程来检查所有需要区分的属性(例如颜色)。

我个人会尝试将产品 ID 添加到页面数据中,在之前的项目中搜索它,如果产品 ID 匹配,则该项目之前被点击过(但客户 可以订购不同的颜色)。

小心使用按钮循环计数器作为 id 值,甚至是图像源字符串 - 很容易想象它们可能会出错或受到您无法控制的页面更改的影响。

非常感谢@traktor 给我的帮助,我能够想出解决这个问题的方法。我为每个产品添加了一个 data-prodid,然后将其作为 'id' 传递给 localstorage。然后我检查我的数组中是否有任何元素包含我正在单击的相同 ID,如果有任何结果,则会执行警报。否则,元素将被保存。

let addCartItemButtons = document.getElementsByClassName('product-description-add')
for (let i = 0; i < addCartItemButtons.length; i++){
    let button = addCartItemButtons[i]
    button.addEventListener('click', function(event){
        let buttonClicked = event.target
        let getProdId = buttonClicked.parentElement.parentElement.parentElement.getAttribute('data-prodid')
        let getTitle = buttonClicked.parentElement.parentElement.parentElement.querySelector('.product-title').innerText
        let getImage = buttonClicked.parentElement.parentElement.parentElement.querySelector('.product-header img').src
        let getColor = buttonClicked.parentElement.parentElement.querySelector('.product-description-text li span').innerText
        let getSize = buttonClicked.parentElement.parentElement.querySelector('.product-description-text li select').value
        let getPrice = buttonClicked.parentElement.parentElement.querySelector('.product-description-price').innerText
        let getSpan = buttonClicked.parentElement.parentElement.querySelector('li span').getAttribute('id')
        let oldItems = JSON.parse(localStorage.getItem('newProduct')) || [];
        let newItem = {
            'id': getProdId,
            'title': getTitle,
            'image': getImage,
            'color': getColor,
            'size': getSize,
            'price': getPrice,
            'spanid': getSpan,
        };
        
        if(localStorage.getItem('newProduct') == null) {
            oldItems.push(newItem);
            localStorage.setItem('newProduct', JSON.stringify(oldItems));
        } else {
            let data = JSON.parse(localStorage.getItem('newProduct'))
            let idCheck = data.filter(x => x.id === newItem.id).map(x => x.foo);
            let idCheckResults = idCheck.length
            if(idCheckResults > 0){
                alert('element already added')
            }else{
                oldItems.push(newItem);
                localStorage.setItem('newProduct', JSON.stringify(oldItems));
            }
        }
        let windowCartProducts = JSON.parse(window.localStorage.getItem("newProduct"));
        let productsInCart = document.getElementById('cartProducts')
        let productsAdded = 0
        for(let i = 0; i < windowCartProducts.length; i++){
            productsAdded = windowCartProducts.length
        }
        productsInCart.innerHTML = productsAdded + `<i class="fas fa-shopping-cart"></i>`
    })
}