Удаление определенного элемента из localStorage

90
10

Я добавляю некоторые элементы в localStorage, используя jQuery/JS, и все это прекрасно, но при попытке удалить определенный элемент в массиве (если он тот же элемент) оказывается затруднительным.


В моих консольных журналах (для тестирования), кажется, очищается [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
}
]

введите описание изображения здесь

спросил(а) 2021-01-19T13:40:38+03:00 6 месяцев, 1 неделя назад
1
Решение
99

Никогда не добавляйте/удаляйте элементы из массива, итерации по нему с помощью "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():

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

Кроме того, вы сравниваете localData с литеральной строкой 'null', которая является беспредметной. В этом случае ваше второе условие - if (!localData) и будет обрабатывать его правильно.

ответил(а) 2021-01-19T13:40:38+03:00 6 месяцев, 1 неделя назад
45

У вас есть дополнительная ошибка в коде, вы пишете


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

ответил(а) 2021-01-19T13:40:38+03:00 6 месяцев, 1 неделя назад
46

Проблема заключается в использовании вашего метода сплайсинга. Обратите внимание, что согласно MDN splice изменяет массив на месте и возвращает новый массив, содержащий удаленные элементы. Поэтому, когда вы используете цикл и пытаетесь удалить некоторые элементы, сращивание приведет к смещению элементов. Это происходит из-за постепенного повторения массива, когда вы его сплайсируете, массив изменяется на месте, поэтому элементы "сдвинуты", и вы в конечном итоге пропускаете итерацию некоторых. Looping назад исправляет это, потому что вы не зацикливаетесь в том направлении, в котором вы сращиваете.


Решение 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;


Ссылка рабочего буфера здесь.
После этого нет проблем с получением и настройкой вашего локального хранилища.

ответил(а) 2021-01-19T13:40:38+03:00 6 месяцев, 1 неделя назад
-5

OK. Ты собираешься пинать себя. При первом запуске из 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>

ответил(а) 2021-01-19T13:40:38+03:00 6 месяцев, 1 неделя назад
-5

Вы мутируете массив, сплайсируя его. Единственными элементами 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');
}
}
}
}
});

ответил(а) 2021-01-19T13:40:38+03:00 6 месяцев, 1 неделя назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема