我如何将本地存储用于待办事项列表?

我被要求有一个待办事项列表并通过本地存储保存每个任务(用户提供的以及原始的)。我的老师对完全不同的东西做了一个非常简单的演示,我花了几个小时试图弄清楚。当我查看解决方案时,老实说,我无法弄清楚。它看起来很复杂,我什至不知道从哪里开始。如果有人可以给我任何提示,那就太棒了!


我的代码:


let ul = document.querySelector('ul');


let newItem = document.querySelector('input[type=text]');

let checkbox = document.createElement('input');

checkbox.setAttribute('type', 'checkbox');


function output() {

    let newTodo = document.createElement('li');

    newTodo.innerText = newItem.value;

    newTodo.classList.add('todo');

    let ulAppend = ul.append(newTodo);

    ul.append(newTodo);

    let checkboxAppend = newTodo.append(checkbox);

    newTodo.append(checkbox);

    newItem.value = '';

}


let button = document.querySelector('.btn');

button.addEventListener('click', output);


ul.addEventListener('click', function(e) {

    if (e.target.tagName === 'LI') {

        e.target.remove();

    } else if (e.target.tagName === 'INPUT') {

        e.target.parentElement.classList.toggle('finished');

    }

});

我老师的代码/本地存储方案:


const todoForm = document.getElementById("newTodoForm");

const todoList = document.getElementById("todoList");


// retrieve from localStorage

const savedTodos = JSON.parse(localStorage.getItem("todos")) || [];

for (let i = 0; i < savedTodos.length; i++) {

  let newTodo = document.createElement("li");

  newTodo.innerText = savedTodos[i].task;

  newTodo.isCompleted = savedTodos[i].isCompleted ? true : false;

  if (newTodo.isCompleted) {

    newTodo.style.textDecoration = "line-through";

  }

  todoList.appendChild(newTodo);

}


todoForm.addEventListener("submit", function(event) {

  event.preventDefault();

  let newTodo = document.createElement("li");

  let taskValue = document.getElementById("task").value;

  newTodo.innerText = taskValue;

  newTodo.isCompleted = false;

  todoForm.reset();

  todoList.appendChild(newTodo);


  // save to localStorage

  savedTodos.push({ task: newTodo.innerText, isCompleted: false });

  localStorage.setItem("todos", JSON.stringify(savedTodos));

});


即使我的代码更简单(至少据我所知),它的工作原理与他的代码完全一样。


qq_笑_17
浏览 106回答 3
3回答

qq_花开花谢_0

本地存储将 JSON 对象保存到用户的计算机。您应该创建一个待办事项数组,将该数组附加到每个新待办事项中,然后将该项目设置为本地存储。let ul = document.querySelector('ul');const savedTodos = JSON.parse(localStorage.getItem("todos")) || []; // Retrieves local storage todo OR creates empty array if none existlet newItem = document.querySelector('input[type=text]');let checkbox = document.createElement('input');checkbox.setAttribute('type', 'checkbox');function output() {&nbsp; &nbsp; let newTodo = document.createElement('li');&nbsp; &nbsp; newTodo.innerText = newItem.value;&nbsp; &nbsp; newTodo.classList.add('todo');&nbsp; &nbsp; ul.append(newTodo);&nbsp; &nbsp; newTodo.append(checkbox);&nbsp; &nbsp; savedTodos.push({task: newItem.value, isCompleted: false}); // Appends the new todo to array&nbsp; &nbsp; localStorage.setItem("todos", JSON.stringify(savedTodos)); //Converts object to string and stores in local storage&nbsp; &nbsp; newItem.value = '';}

九州编程

我已经用一些评论对您发布的解决方案进行了注释,以帮助您逐步完成它。// Retrieve elements and store them in variablesconst todoForm = document.getElementById("newTodoForm");const todoList = document.getElementById("todoList");// Get data stored in localStorage under the key "todos".// The data type will be a string (local storage can only store strings).// JSON is a global object that contains methods for working with data represented as strings.// The `||` syntax is an OR operator and is used here to set an empty array as a fallback in case `localStorage` is emptyconst savedTodos = JSON.parse(localStorage.getItem("todos")) || [];// Create a loop the same length as the list of todosfor (let i = 0; i < savedTodos.length; i++) {&nbsp; // Create an <li> element in memory (does not appear in the document yet)&nbsp; let newTodo = document.createElement("li");&nbsp; // Set the inner text of that new li with the contents from local storage.&nbsp; // The savedTodos[i] is accessing data in the localStorage array.&nbsp; // The [i] is a different number each loop.&nbsp; // The `.task` is accessing 'task' property on the object in the array.&nbsp; newTodo.innerText = savedTodos[i].task;&nbsp; // Create a new property on the element called `isCompleted` and assign a boolean value.&nbsp; // This is only accessible in code and will not show up when appending to the DOM.&nbsp; newTodo.isCompleted = savedTodos[i].isCompleted ? true : false;&nbsp; // Check the value we just set.&nbsp; if (newTodo.isCompleted) {&nbsp; &nbsp; // Create a style for the element if it is done (strike it out)&nbsp; &nbsp; newTodo.style.textDecoration = "line-through";&nbsp; }&nbsp; // Actually append the new element to the document (this will make it visible)&nbsp; todoList.appendChild(newTodo);}// `addEventListener` is a function that registers some actions to take when an event occurs.// The following tells the browser - whenever a form is submitted, run this function.todoForm.addEventListener("submit", function(event) {&nbsp; // Don't try to send the form data to a server. Stops page reloading.&nbsp; event.preventDefault();&nbsp; // Create a <li> element in memory (not yet visible in the document)&nbsp; let newTodo = document.createElement("li");&nbsp; // Find element in the document (probably a input element?) and access the text value.&nbsp; let taskValue = document.getElementById("task").value;&nbsp; // Set the text of the <li>&nbsp; newTodo.innerText = taskValue;&nbsp; // Set a property on the <li> call `isCompleted`&nbsp; newTodo.isCompleted = false;&nbsp; // Empty out all the input fields in the form&nbsp; todoForm.reset();&nbsp; // Make the new <li> visible in the document by attaching it to the list&nbsp; todoList.appendChild(newTodo);&nbsp; // `push` adds a new element to the `savedTodos` array. In this case, an object with 2 properties.&nbsp; savedTodos.push({ task: newTodo.innerText, isCompleted: false });&nbsp; // Overwrite the `todos` key in local storage with the updated array.&nbsp; // Use the JSON global object to turn an array into a string version of the data&nbsp; // eg [1,2,3] becomes "[1,2,3]"&nbsp; localStorage.setItem("todos", JSON.stringify(savedTodos));});// This tells the browser - whenever the todoList is clicked, run this function.// The browser will call the your function with an object that has data about the event.todoList.addEventListener("click", function(event) {&nbsp; // the `target` of the event is the element that was clicked.&nbsp; let clickedListItem = event.target;&nbsp; // If that element has a property called `isCompleted` set to true&nbsp; if (!clickedListItem.isCompleted) {&nbsp; &nbsp; // update the styles and toggle the `isCompleted` property.&nbsp; &nbsp; clickedListItem.style.textDecoration = "line-through";&nbsp; &nbsp; clickedListItem.isCompleted = true;&nbsp; } else {&nbsp; &nbsp; clickedListItem.style.textDecoration = "none";&nbsp; &nbsp; clickedListItem.isCompleted = false;&nbsp; }&nbsp; // The code above changes the documents version of the data (the elements themselves)&nbsp; // This loop ensures that the array of todos data is kept in sync with the document&nbsp; // Loop over the array&nbsp; for (let i = 0; i < savedTodos.length; i++) {&nbsp; &nbsp; // if the item in the array has the same text as the item just clicked...&nbsp; &nbsp; if (savedTodos[i].task === clickedListItem.innerText) {&nbsp; &nbsp; &nbsp; // toggle the completed state&nbsp; &nbsp; &nbsp; savedTodos[i].isCompleted = clickedListItem.isCompleted;&nbsp; &nbsp; &nbsp; // Update the localStorage with the new todos array.&nbsp; &nbsp; &nbsp; localStorage.setItem("todos", JSON.stringify(savedTodos));&nbsp; &nbsp; }&nbsp; }});请记住,您的待办事项列表中有 2 个状态来源。一个是文档的外观,另一个是todos数据数组。许多挑战来自确保这两个保持同步。如果文档以某种方式显示其中一个列表项被划掉,但您的数据数组显示所有todos未完成,那么哪个版本是正确的?这里没有正确的答案,但状态管理将是您未来设计应用程序时可能会考虑的问题。Redux是一个很好的 js 库,具有很好理解的模式,可以帮助解决这个问题。希望这最后的评论不会混淆太多。祝你好运!

温温酱

重要的部分是(反)序列化数据。这意味着:localStorage从(&nbsp;JSON.parse(localStorage.getItem("todos")) || [])读取我们添加默认值[],因为如果todos键不存在,我们将得到null并且我们期望一个列表保存到localStorage(&nbsp;localStorage.setItem("todos", JSON.stringify(savedTodos)))我们需要JSON.parse和它的补充操作JSON.stringify来解析和保存字符串,因为 localStorage 只能存储字符串。在您的情况下,您需要从 localStorage 读取数据并呈现初始列表。要将其保存到 localStorage,您必须再次序列化数据。请参阅下面的片段(链接到工作JSFIDDLE,因为下面的示例在 StackOverflow 沙箱环境中不起作用):let ul = document.querySelector('ul');let newItem = document.querySelector('input[type=text]');const Store = {&nbsp; serialize () {&nbsp; &nbsp; return [].slice.call(document.querySelectorAll("li")).map(c => {&nbsp; &nbsp; &nbsp; return {&nbsp; &nbsp; &nbsp; &nbsp; text: c.textContent,&nbsp; &nbsp; &nbsp; &nbsp; finished: c.querySelector("input").checked&nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; })&nbsp; },&nbsp; get () {&nbsp; &nbsp; return JSON.parse(localStorage.getItem("todos")) || []&nbsp; },&nbsp; save () {&nbsp; &nbsp; return localStorage.setItem("todos", JSON.stringify(Store.serialize()))&nbsp; }}const firstItems = Store.get()firstItems.forEach(it => {&nbsp; output(it.text, it.finished)})function output(v, finished) {&nbsp; let newTodo = document.createElement('li');&nbsp; newTodo.innerText = v || newItem.value;&nbsp; newTodo.classList.add('todo');&nbsp; let ulAppend = ul.append(newTodo);&nbsp; ul.append(newTodo);&nbsp; // Create a checkbox for each item&nbsp; let checkbox = document.createElement('input');&nbsp; if (finished) {&nbsp; &nbsp; checkbox.checked = true&nbsp; }&nbsp; checkbox.setAttribute('type', 'checkbox');&nbsp; let checkboxAppend = newTodo.append(checkbox);&nbsp; newTodo.append(checkbox);&nbsp; newItem.value = '';}let button = document.querySelector('.btn');button.addEventListener('click', () => {&nbsp; &nbsp; output()&nbsp; Store.save()});ul.addEventListener('click', function(e) {&nbsp; if (e.target.tagName === 'LI') {&nbsp; &nbsp; e.target.remove();&nbsp; } else if (e.target.tagName === 'INPUT') {&nbsp; &nbsp; e.target.parentElement.classList.toggle('finished');&nbsp; }&nbsp; // Update the value in localStorage when you delete or add a new item&nbsp; Store.save()});<ul></ul><input type="text" /> <button class="btn">Submit</button>我添加了Store变量以简化您在 localStorage 中获取和设置数据的方式。serialize 方法将从列表中读取 TODO。document.querySelectorAll("li")返回 a&nbsp;NodeList,但通过这样做[].slice.call(...)我们将其转换为 a&nbsp;Array。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

JavaScript