从localStorage中删除特定项目

3
我正在使用jQuery / JS将一些项目添加到localStorage中,这很好,但是试图删除数组中的特定项目(如果是同一个项目)非常困难。在我的控制台日志中(用于测试),它似乎清除了[Object],但没有更新密钥。也许我的层次结构有误...有什么想法吗?
//
function addToStorage(elem, name) {

    localData = localStorage.getItem(name + 'Storage');
    var typefaces;

    if (localData == 'null' || !localData) {
        typefaces = [];
    } else {
       typefaces = JSON.parse(localData);
    }

    typefaceID = elem.find('input').val();
    typefaceName = elem.find('input').attr('data-name');
    typefacePrice = elem.find('input').attr('data-price');
    typefaceQty = 1;

    $.each(typefaces, function(index, value) {
        if (value !== null) {
            if (value.id == typefaceID) {
                if (name == 'drf') {
                    //console.log(index);
                    //console.log(typefaces);
                    typefaces.splice(index, 1);
                    //console.log(typefaces);
                }
            }
        }
    });

    typefaces.push({
        'id': typefaceID,
        'name': typefaceName,
        'price': typefacePrice,
        'qty': typefaceQty
    });

    localStorage.setItem(name + 'Storage', JSON.stringify(typefaces));

}

//
$(document).on('click', 'summary.cart td.font', function(e) {
    e.preventDefault();
    addTo = $(this);
    addTo.each(function() {
        addToStorage(addTo, 'drf');
    });
});

这是一个添加了数据后的localData示例。

[  
   {  
      "id":"dr-raymond-desktop-40374",
      "name":"DR-Raymond",
      "format":"Desktop (OTF)",
      "price":"15.00",
      "qty":1
   },
   {  
      "id":"dr-raymond-webfont-39949",
      "name":"DR-Raymond",
      "format":"Webfont (WOFF)",
      "price":"15.00",
      "qty":1
   }
]

enter image description here


你能否提供你的JSON本地数据的格式或任何Fiddle链接,以便更加详细说明吗? - breakit
@breakit,这就添加到原问题中了,谢谢! - John the Painter
“更新键”是什么意思? - Xavier J
@XavierJ 抱歉如果您在检查localStorage时从Chrome DevTools看到了我的图像附件。在这种情况下,“键”是localStorage,“值”是内容(localData数组)。 - John the Painter
@JohnthePainter 请检查我的答案,你的代码还有一个额外的错误。 - user2560539
5个回答

4
不要在使用“foreach”遍历数组时添加/删除元素。相反,请尝试以下方法:
for (index = typefaces.length - 1; index >= 0; index--){
    value = typefaces[index];
    if (value !== null) {
        if (value.id == typefaceID) {
            if (name == 'drf') {
                typefaces.splice(index, 1);
            }
        }
    }
});

另一种更优雅的方式是使用ES6的filter()方法:

typefaces = typefaces.filter(value => !(value && value.id == typefaceID && name == "drf"));

此外,您正在将localData与文本字符串'null'进行比较,这有点毫无意义。在此情况下,您的第二个条件-if (!localData)已足够,并且将正确处理它。

2
你说的“remove”是什么意思?看起来你的代码总是会在删除的位置推入一个新项目。 - alonkol
是的,我刚刚想到了哈哈!我不想让它推送已经被删除的那一个,显然。 - John the Painter
你似乎正试图实现某种“切换”行为。你将此函数命名为“addToStorage”。你是在尝试除了向存储添加元素之外的其他操作吗? - alonkol
是的,如原问题所描述的,这是一种“切换”类型。'addToStorage' 可能命名不太好,但当他们点击要添加的项目时...如果他们点击已添加的项目,则应将其从localStorage中删除。 - John the Painter
1
另一种获取此布尔值的方法是再次使用filter():found = typefaces.filter(value => (value && value.id == typefaceID && name == "drf")).length > 0; - alonkol
显示剩余7条评论

0
问题在于您使用了错误的splice方法。根据MDNsplice在原地修改数组并返回一个包含已删除元素的新数组。所以,在使用循环并尝试删除一些元素时,splice会使元素发生移动。这是因为在迭代递增的数组时,当您对其进行切片时,数组会在原地被修改,因此项目会被“移位”,导致跳过某些迭代。倒序循环可以解决这个问题,因为您不会在进行切片的方向上循环。

解决方案1

在进行切片时反向循环。

for(var i = typefaces.length; i--;)
{
            if (typefaces[i] !== null) 
            {

                if (typefaces[i] == typefaceID) 
                {
                        typefaces.splice(i, 1);
                }
            }
 }

工作的二进制链接 在这里

解决方案2

通常生成一个新数组比修改现有数组更快。因此,您的代码将如下所示

ty = [];
   $.each(typefaces, function(index, value) {
        if (value !== null) {

            if (value.id != typefaceID) {
                    ty.push(value);
            }
        }
    });
  typefaces = ty;

工作的二进制链接在这里。 之后,在获取和设置您的localStorage时没有发现任何问题。


如果您在使用localStorage时遇到任何问题,请在此处联系我。 - breakit

0

你的代码中还有一个错误,你写成了

if (value !== null) {
    if (value.id == typefaceID) {
        // name will always have the value drf 
        // since you pass it in your function
        // when you call it addToStorage(addTo, 'drf');
        if (name == 'drf') {
            typefaces.splice(index, 1);
        }
    }
}

应该是这样的

if (value !== null) {
    if (value.id == typefaceID) {
        // here the comparison should be between value.name and name
        if (value.name == name) {
            typefaces.splice(index, 1);
        }
    }
}

这也可以写成

if (value !== null) {
    if (value.id == typefaceID && value.name == name) {
            typefaces.splice(index, 1);
    }
}

-1

你正在通过splice方法改变数组。被重写的只有那些留在数组中的localstorage项。

因此,在从数组中删除对象时,也要从存储中删除该项。

$.each(typefaces, function(index, value) {
        if (value !== null) {
            if (value.id == typefaceID) {
                if (name == 'drf') {
                    //console.log(index);
                    //console.log(typefaces);
                    var removedTypeFace = typefaces.splice(index, 1);
                    //console.log(typefaces);

                    if(removedTypeFace) {
                        localStorage.removeItem(removedTypeFace.name + 'Storage');
                    }
                }
            }
        }
    });

1
谢谢。'localStorage.removeItem()' 是否只会删除整个键,而不是从键中删除splice? - John the Painter
@JohnthePainter,你需要使用splice从数组中删除它,并从本地存储中删除该属性。 - Sushanth --
1
splice 的使用是有意义的,但是 localStorage.removeItem(removedTypeFace.name + 'Storage'); 是否正确地从本地存储中删除该属性呢? - John the Painter

-1

好的。你会后悔的。第一次从localStorage中取出时,getItem方法确实返回null值,但您正在尝试将其与字符串(用引号括起来的'null')进行比较。失败了。我将localData =='null'更改为localData == null

表达式的第二部分尝试查看从getItem返回的值是否已定义,这是很好的。我通过typeof更明确地修改了它。

显式变量声明也有所帮助。

function addToStorage(elem, name) {

    var localData = localStorage.getItem(name + 'Storage');
    var typefaces;

    if (localData == null || typeof(localData) == 'undefined') {
        typefaces = [];
    } else {
       typefaces = JSON.parse(localData);
    }

    var typefaceID = elem.find('input').val();
    var typefaceName = elem.find('input').attr('data-name');
    var typefacePrice = elem.find('input').attr('data-price');
    var typefaceQty = 1;

    $.each(typefaces, function(index, value) {
        if (value !== null) {
            if (value.id == typefaceID) {
                if (name == 'drf') {
                    //console.log(index);
                    //console.log(typefaces);
                    typefaces.splice(index, 1);
                    //console.log(typefaces);
                }
            }
        }
    });

    typefaces.push({
        'id': typefaceID,
        'name': typefaceName,
        'price': typefacePrice,
        'qty': typefaceQty
    });

    localStorage.setItem(name + 'Storage', JSON.stringify(typefaces));

}

//
jQuery(document).on('click', 'summary.cart td.font', function(e) {
    e.preventDefault();
    addTo = $(this);
    addTo.each(function() {
        addToStorage(addTo, 'drf');
    });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<summary class='cart'><table><tr>
<td class='font' >Click Here for Item 1
<input data-name='abc' data-price='2.00' value="Item 1" /></td></tr>
<tr>
<td class='font' >Click Here for Item 2
<input data-name='def' data-price='4.00' value="Item 2" /></td></tr></table>
</summary>


谢谢!但是好像没有从localStorage中删除该项?:( - John the Painter
从数组中删除似乎很好(如果我在删除之前和之后记录控制台日志,则显示它从[Object]更改为[],但在localStorage中仍然存在)。也许我的这一行 localStorage.setItem(name + 'Storage', JSON.stringify(typefaces)); 没有做我想象的那样... - John the Painter

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接