为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

qq_笑_17 2022-10-13 17:11:07
我被要求有一个待办事项列表并通过本地存储保存每个任务(用户提供的以及原始的)。我的老师对完全不同的东西做了一个非常简单的演示,我花了几个小时试图弄清楚。当我查看解决方案时,老实说,我无法弄清楚。它看起来很复杂,我什至不知道从哪里开始。如果有人可以给我任何提示,那就太棒了!我的代码: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 localStorageconst 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));});即使我的代码更简单(至少据我所知),它的工作原理与他的代码完全一样。
查看完整描述

3 回答

?
qq_花开花谢_0

TA贡献1835条经验 获得超7个赞

本地存储将 JSON 对象保存到用户的计算机。您应该创建一个待办事项数组,将该数组附加到每个新待办事项中,然后将该项目设置为本地存储。


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


const savedTodos = JSON.parse(localStorage.getItem("todos")) || []; // Retrieves local storage todo OR creates empty array if none exist

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

    ul.append(newTodo);

    newTodo.append(checkbox);


    savedTodos.push({task: newItem.value, isCompleted: false}); // Appends the new todo to array

    localStorage.setItem("todos", JSON.stringify(savedTodos)); //Converts object to string and stores in local storage


    newItem.value = '';

}


查看完整回答
反对 回复 2022-10-13
?
九州编程

TA贡献1785条经验 获得超4个赞

我已经用一些评论对您发布的解决方案进行了注释,以帮助您逐步完成它。


// Retrieve elements and store them in variables

const 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 empty

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


// Create a loop the same length as the list of todos

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

  // Create an <li> element in memory (does not appear in the document yet)

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

  // Set the inner text of that new li with the contents from local storage.

  // The savedTodos[i] is accessing data in the localStorage array.

  // The [i] is a different number each loop.

  // The `.task` is accessing 'task' property on the object in the array.

  newTodo.innerText = savedTodos[i].task;

  // Create a new property on the element called `isCompleted` and assign a boolean value.

  // This is only accessible in code and will not show up when appending to the DOM.

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

  // Check the value we just set.

  if (newTodo.isCompleted) {

    // Create a style for the element if it is done (strike it out)

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

  }

  // Actually append the new element to the document (this will make it visible)

  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) {

  // Don't try to send the form data to a server. Stops page reloading.

  event.preventDefault();

  // Create a <li> element in memory (not yet visible in the document)

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

  // Find element in the document (probably a input element?) and access the text value.

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

  // Set the text of the <li>

  newTodo.innerText = taskValue;

  // Set a property on the <li> call `isCompleted`

  newTodo.isCompleted = false;

  // Empty out all the input fields in the form

  todoForm.reset();

  // Make the new <li> visible in the document by attaching it to the list

  todoList.appendChild(newTodo);


  // `push` adds a new element to the `savedTodos` array. In this case, an object with 2 properties.

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

  // Overwrite the `todos` key in local storage with the updated array.

  // Use the JSON global object to turn an array into a string version of the data

  // eg [1,2,3] becomes "[1,2,3]"

  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) {

  // the `target` of the event is the element that was clicked.

  let clickedListItem = event.target;


  // If that element has a property called `isCompleted` set to true

  if (!clickedListItem.isCompleted) {

    // update the styles and toggle the `isCompleted` property.

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

    clickedListItem.isCompleted = true;

  } else {

    clickedListItem.style.textDecoration = "none";

    clickedListItem.isCompleted = false;

  }


  // The code above changes the documents version of the data (the elements themselves)

  // This loop ensures that the array of todos data is kept in sync with the document

  // Loop over the array

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

    // if the item in the array has the same text as the item just clicked...

    if (savedTodos[i].task === clickedListItem.innerText) {

      // toggle the completed state

      savedTodos[i].isCompleted = clickedListItem.isCompleted;

      // Update the localStorage with the new todos array.

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

    }

  }

});

请记住,您的待办事项列表中有 2 个状态来源。一个是文档的外观,另一个是todos数据数组。许多挑战来自确保这两个保持同步。


如果文档以某种方式显示其中一个列表项被划掉,但您的数据数组显示所有todos未完成,那么哪个版本是正确的?这里没有正确的答案,但状态管理将是您未来设计应用程序时可能会考虑的问题。Redux是一个很好的 js 库,具有很好理解的模式,可以帮助解决这个问题。希望这最后的评论不会混淆太多。祝你好运!


查看完整回答
反对 回复 2022-10-13
?
温温酱

TA贡献1752条经验 获得超4个赞

重要的部分是(反)序列化数据。这意味着:

  • localStorage从( JSON.parse(localStorage.getItem("todos")) || [])读取

    我们添加默认值[],因为如果todos键不存在,我们将得到null并且我们期望一个列表

  • 保存到localStoragelocalStorage.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 = {

  serialize () {

    return [].slice.call(document.querySelectorAll("li")).map(c => {

      return {

        text: c.textContent,

        finished: c.querySelector("input").checked

      }

    })

  },

  get () {

    return JSON.parse(localStorage.getItem("todos")) || []

  },

  save () {

    return localStorage.setItem("todos", JSON.stringify(Store.serialize()))

  }

}


const firstItems = Store.get()

firstItems.forEach(it => {

  output(it.text, it.finished)

})


function output(v, finished) {

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

  newTodo.innerText = v || newItem.value;

  newTodo.classList.add('todo');

  let ulAppend = ul.append(newTodo);

  ul.append(newTodo);


  // Create a checkbox for each item

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

  if (finished) {

    checkbox.checked = true

  }

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


  let checkboxAppend = newTodo.append(checkbox);

  newTodo.append(checkbox);

  newItem.value = '';

}


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

button.addEventListener('click', () => {

    output()

  Store.save()

});


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

  }

  // Update the value in localStorage when you delete or add a new item

  Store.save()

});

<ul></ul>

<input type="text" /> <button class="btn">Submit</button>

我添加了Store变量以简化您在 localStorage 中获取和设置数据的方式。

serialize 方法将从列表中读取 TODO。document.querySelectorAll("li")返回 a NodeList,但通过这样做[].slice.call(...)我们将其转换为 a Array


查看完整回答
反对 回复 2022-10-13
  • 3 回答
  • 0 关注
  • 105 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号