Javascript 从本地存储中删除特定项

Javascript 从本地存储中删除特定项,javascript,jquery,html,local-storage,Javascript,Jquery,Html,Local Storage,我使用jQuery/JS向localStorage添加了一些项,这很好,但是尝试删除数组中的特定项(如果是同一项)是很困难的 在我的控制台日志(用于测试)中,它似乎清除了[Object],但没有更新密钥。也许我的等级制度错了。。。有什么想法吗 // function addToStorage(elem, name) { localData = localStorage.getItem(name + 'Storage'); var typefaces; if (loca

我使用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
   }
]

您正在通过拼接阵列对其进行变异。正在重新写入的唯一本地存储项是留在阵列中的项

$.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');
                    }
                }
            }
        }
    });
因此,当您从阵列拼接对象时,请从存储器中删除该项

$.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');
                    }
                }
            }
        }
    });

在使用“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():


另外,您正在将
localData
与文本字符串
'null'
进行比较,这是一种毫无意义的比较。第二个条件-
如果(!localData)
在这种情况下就足够了,并且可以正确处理它。

确定。你会踢自己的。第一次从localStorage中提取时,
getItem
方法确实返回一个
null
值,但您试图将其与字符串进行比较(
'null'
,在引号中)。失败。我将
localData==null'
更改为
localData==null

表达式的第二部分尝试查看从
getItem
返回的值是否已实际定义,这很好。我通过
typeof
将其更改为更加明确

显式变量声明也有帮助

函数addToStorage(元素、名称){
var localData=localStorage.getItem(名称+‘存储’);
var字体;
if(localData==null | | typeof(localData)=='undefined'){
字体=[];
}否则{
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(字体、函数(索引、值){
如果(值!==null){
if(value.id==字体id){
如果(名称=='drf'){
//控制台日志(索引);
//控制台日志(字体);
字体.拼接(索引1);
//控制台日志(字体);
}
}
}
});
字体.推送({
“id”:字体id,
“名称”:字体名称,
“价格”:字体价格,
“数量”:字体数量
});
setItem(名称+Storage',JSON.stringify(字体));
}
//
jQuery(document).on('click','summary.cart td.font',函数(e){
e、 预防默认值();
addTo=$(本);
addTo.each(函数(){
添加到存储(添加到“drf”);
});
});

单击此处查看项目1
单击此处查看项目2

问题在于拼接方法的使用。请注意,根据
splice
修改在位数组并返回包含已删除元素的新数组。因此,当使用回路并试图移除某些元件时,拼接会使元件发生移位。这是因为通过数组进行增量迭代,当您拼接它时,数组会在适当的位置进行修改,因此项目会“移位”,您最终会跳过某些项目的迭代。反向循环修复了这一问题,因为您没有在拼接的方向上循环

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

                if (typefaces[i] == typefaceID) 
                {
                        typefaces.splice(i, 1);
                }
            }
 }
解决方案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;
工作箱链接为。
在这之后,在获取和设置本地存储时没有发现任何问题。

如果代码中还有一个错误,您可以编写

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);
    }
}

谢谢“localStorage.removeItem()”是否只删除整个密钥而不是密钥中的拼接?@JohnthePainter您必须同时删除这两个密钥,使用
splice
将其从数组中删除,然后从本地存储中删除该属性。拼接是有意义的,但它是
localStorage.removeItem(removedTypeFace.name+“存储”)从本地存储中删除该属性的正确方法?能否为json localdata或任何fiddle链接提供一种格式,使其更具解释性?@breakit这是添加到原始问题中的内容,谢谢!“更新密钥”是什么意思?@XavierJ如果您在检查本地存储时看到Chrome DevTools中的我的图像附件,请原谅。此实例中的“key”是localStorage,“value”是contents(localData数组)@johnthepaninter请检查我的答案您的代码中还有一个错误。谢谢。它仍然没有将其从本地存储中删除。如果我单击它一次,它会将其添加到本地存储中,但如果我再次单击它以删除,它不会。你说的“删除”是什么意思?似乎你的代码总是会推一个新的项目,而不是删除的项目。是的,我刚刚解决了这个问题哈哈!显然,我不希望它推送已删除的对象。我尝试将推送放在for循环之前,但它似乎总是返回空数组。获取此布尔值的另一种方法是再次使用filter():
found=typefaces.filter(value=>(value&&value.id==typefaceID&&name==drf”)。长度>0
;谢谢你!但这似乎并没有从本地存储中删除该项:(它似乎可以从数组中很好地删除它(如果在删除之前和之后I console.log数组,它会显示它从[Object]变为[],但在本地存储中它似乎仍然存在)。也许我的行
localStorage.setItem(name+'Storage',JSON.stringify(typefaces))
没有做我认为应该做的事……如果您遇到本地存储方面的任何问题,请告诉我