Как правильно сохранять TODO list в LocalStorage?

Нужен совет как правильно сохранить список дел в LocalStorage. У меня есть масив, при добавлении нового дела, буду записывать его innerHTML и свойство check, в объект, потом этом объект пушить в масив. В результате получиться масив с объектами (делами). Который я уже спокойно буду кидать в LocalStorage. Но у меня проблема, при удалении дела, нужно удалять и его объект в масиве, и я не очень понимаю как это реализовать. Может есть какие-то другие варианты. Заранее благодарю! P.s. как вариант в LS можно сохранить целый container с делами. К примеру:

`localStorage.setItem("todos", container.innerHTML);`

Насколько это уместно?


Ответы (1 шт):

Автор решения: MoloF

localStorage в песке отключен, поэтому для полного тестирования можно посетить JSFIDDLE

Не знаю насколько качественно и понятно, но делал в первый раз подобное.

Сначала думал будет не тривиальная и довольно простая задача, но потом углубился в Proxy и небольшое взаимодействие и кода так прибавилось.

Здесь есть один важный аспект - это Proxy.

Я его использовал только для того, чтобы следить за состоянием массива и проверять, не был ли он изменен.

После чего я запускал рендер и сохранял изменения.

Так же добавил смену состояния через чекбокс, удаление и добавление с помощью prompt.

Ответ оставляю общим, мне кажется я там перебрал с кодом и можно было сделать легче но я не знаю как (или просто лень).

(изначально все было на функциях и я перенес на классы, ибо обилие функций кровоточило глаза)

class Todo {
	constructor() {
		this.list = document.querySelector('ul');

		const proxyHandle = {
			set: (target, property, value) =>
				this.proxySetHandle(target, property, value),
		};
	
		this.tasks = this.getTasks();
		this.proxyTasks = new Proxy(this.tasks, proxyHandle);
		
		this.renderTask();
		
		const button = document.querySelector('button');
		button.onclick = () => this.createTask();
	}
	
	taskSchema(status, name) {
		const wrapper = document.createElement('li');
		wrapper.innerHTML = (`
			<input type="checkbox" ${status ? 'checked' : null}>
			<span>${name}</span>
			<i>x</i>
		`);
		return wrapper;
	}
	
	taskChangeStatus(index, status) {} 
	
	getTasks() {
		return localStorage.getItem('tasks')
			? JSON.parse(localStorage.getItem('tasks'))
			: []
	}
	saveTasks() {
		localStorage.setItem('tasks', JSON.stringify(this.tasks));
	}
	createTask() {
		const name = prompt('Введите название задания');
		if (name.length <= 0 || name.length > 100) return;
		this.proxyTasks.push({
			status: false,
			name
		});
	}
	
	changeTaskStatus(index, status) {
		this.proxyTasks[index].status = status;
		this.saveTasks();
	}
	removeTask(index) {
		this.proxyTasks.splice(index, 1);
	}
	
	renderTask() {
		this.list.innerHTML = '';
		this.tasks.forEach(task => {
			const schema = this.taskSchema(
				task.status,
				task.name
			);
			
			this.list.appendChild(schema);
		});
		
		const tasks = this.list.querySelectorAll('li');
		
		tasks.forEach((task, index) => {
			const status = task.querySelector('input');
			const remove = task.querySelector('i');
			
			status.onchange = (e) =>
				this.changeTaskStatus(index, e.target.checked);
			
			remove.onclick = () => this.removeTask(index);
		});
	}
	
	proxySetHandle(target, property, value) {
		target[property] = value;
		this.saveTasks();
		this.renderTask();
		return true;
	}
}

new Todo();
ul {
	list-style-type: none;
}

ul li input:checked + span {
	text-decoration: line-through;
}
ul li i {
	color: red;
}
<button>Добавить задание</button>
<ul></ul>

→ Ссылка