这个案例前几天就看了,一直没时间作,今天就把它作出来。这个案例是一个待办事项列表,能够记录本身当天须要作的事情,完成一件就画勾,要是不想要了就删除,能够很好的督促本身完成天天的学习任务啊。看下效果吧。javascript
当我第一次看到这个效果时,从局部出发,个人第一反应就是点击事件的删除和添加操做。可是看视频的时候老师作了需求分析,很仔细的分析了案例的效果,事实证实并无我想的那么简单。确实是添加删除元素的操做,只是对象变了,不是父元素创造元素再添加元素的步骤,而是对存储的操做,最后把存储中的数据渲染到页面。第一次听渲染这个词,懂,也不懂。后来看完整个过程我简单的懂了渲染的意思。仍是菜鸟一个。css
数据存储的格式html
var todoList = [{title:“123”,done:false},{title:“今天学习jQuery”,done:false}]java
创造的元素里包含三部分:复选框、表单输入的内容、删除按钮。jquery
可是咱们存储数据的只须要两部分,就是复选框的状态和表单输入的内容。
在存储数据时,设置对象的两个属性:文本内容和复选框状态。默认复选框的状态是没选中的,由于新建立的元素是待办的。复选框选中(true)是再已完成部分,没选中(false)是待办。web
可是咱们又会创造不少这样的元素,因此就把这些对象放到数组中存储,经过数组的索引号访问。数组
刷新页面数据不丢失,说明咱们的数据是存放在本地存储localStorage中的。
无论是当咱们点击复选框、点击删除键仍是在表单输入内容建立出来的元素,这些通通都是在本地存储中,页面中显示的数据都是从本地存储中取出来渲染的。
须要明白的是:本地储存的是字符串格式,咱们须要存储的是数组对象格式。因此咱们须要把数组对象格式转换为字符串格式存到本地存储,从本地存储取数据时再把字符串格式转换为数组对象格式。svg
数组对象格式转为字符串格式:JSON.stringify(todoList)
字符串格式转为数组对象格式:JSON.parse(stringDate)学习
var toDo = [{ title: "123", done: false }, { title: "今天学习jQuery", done: false }]; console.log(toDo); console.log(toDo[0].title); localStorage.setItem("todo", toDo); console.log(localStorage.getItem("todo")); var stringDate = JSON.stringify(toDo); localStorage.setItem("todo2", stringDate); console.log(localStorage.getItem("todo2"));
看眼输出就明白了,中间箭头指向的是字符串类型的数据,就是本地存储中存储的数据格式。
上面的存储格式,都弄明白了,接下来就该总结一下需求吧。ui
表单:输入内容,按enter键,创造元素,并添加到待办事件。
实质:按下enter键时,先声明一个数组用来接收保存本地存储中的数据。封装一个方法,专门用来获取本地存储中的数据。再把建立的新元素追加到声明数组。而后把数组再赋值给本地储存,完成更新。最后把本地存储中的数据渲染到页面。设置本地存储的数据一样能够封装一个方法。
数据渲染页面:获取本地存储中的数据,把数据转为数组对象遍历数组,有几条数据就建立几个元素。判断对象done属性的值,true添加到已完成,false添加到待办。
复选框:点击更改复选框的状态,切换到待办或者已完成。实质:点击复选框,先获取本地存储数据,更改复选框的状态,更新本地存储数据,最后渲染页面。
删除键:点击删除当前任务。实质:获取本地存储数据,删除对应被点击的元素,更新本地存储数据,渲染页面。
须要封装的方法:获取本地存储数据、设置保存本地存储数据(更新)、渲染页面。
注意:在封装获取和设置本地存储数据方法时,注意数据格式的转换
JSON.stringify 转为字符串
JSON.parse 转为数组对象
// 读取本地存储的数据 function getLocalStorage() { var date = localStorage.getItem("toDoList"); // 判断本地存储是否为空 if (date != null) { return JSON.parse(date); } else { return []; // 为空返回空数组 } } // 保存本地存储的数据 function setLocalStorage(date) { localStorage.setItem("toDoList", JSON.stringify(date)); }
// 2. 把本地存储数据渲染到页面 function loadPage() { // 2.1 先读取本地存储数据 var date = getLocalStorage(); // 遍历以前先清空页面中的ul和ol的内容 防止后面重复添加 $("#todolist,#donelist").empty(); // 记录已完成和进行中的个数 var toDoCount = 0; var doneCount = 0; // 2.2 遍历本地存储数据 有多少个对象就建立多少个li $.each(date, function (i, ele) { // 根据复选框的状态,决定添加到那个部分 // done为true 加到 donelist中 if (ele.done) { // 自定义属性 id 记录数据在本地存储中的位置 $("#donelist").prepend("<li><input type = 'checkbox' checked><p>" + ele.title + "</p><a href = '#' id=" + i + "></a></li>") // 更新个数 doneCount++; } else { $("#todolist").prepend("<li><input type = 'checkbox'><p>" + ele.title + "</p><a href = '#' id=" + i + "></a></li>") toDoCount++; } }) $("#todocount").text(toDoCount); $("#donecount").text(doneCount); }
<li> <input type="checkbox"> <p>123</p> <a href="#"></a> </li>
// 4. 点击复选框 匹配状态 // 本质是,点击更改本地存储数据中复选框状态,从新渲染页面 $("#todolist,#donelist").on("click", "input", function () { // 读取本地存储数据 var localDate = getLocalStorage(); // 获取被点击的元素的索引 var index = $(this).siblings("a").attr("id"); // 修改数据 localDate[index].done = $(this).prop("checked"); // 更新本地数据 setLocalStorage(localDate); // 从新渲染页面 loadPage(); })
// 记录已完成和进行中的个数 var toDoCount = 0; var doneCount = 0; // 2.2 遍历本地存储数据 有多少个对象就建立多少个li $.each(date, function (i, ele) { // 根据复选框的状态,决定添加到那个部分 // done为true 加到 donelist中 if (ele.done) { // 自定义属性 id 记录数据在本地存储中的位置 $("#donelist").prepend("<li><input type = 'checkbox' checked><p>" + ele.title + "</p><a href = '#' id=" + i + "></a></li>") // 更新个数 doneCount++; } else { $("#todolist").prepend("<li><input type = 'checkbox'><p>" + ele.title + "</p><a href = '#' id=" + i + "></a></li>") toDoCount++; } }) $("#todocount").text(toDoCount); $("#donecount").text(doneCount);
$(function () { // 需求分析: // 在表单中输入内容,按enter键添加待办事项 // 点击表单能够切换状态 // 点击删除能够删除数据 // 当刷新页面时,页面的数据不会丢失 —— localStorage存储方式 // 这就意味着无论咱们点击的是什么都是对本地存储的数据进行操做 // 操做完成后把本地存储的数据渲染到页面中 // 一开始就要渲染页面 保证数据不丢失 loadPage(); // 1. 按回车键把数据添加到本地存储 $("#title").on("keyup", function (e) { if (e.keyCode === 13) { if ($(this).val() === "") { alert("请输入您要输入的内容") } else { // 首先声明一个数组用来接收本地存储的数据 var localDate = getLocalStorage(); console.log(localDate); // 把新元素追加到本地存储 localDate.push({ title: $(this).val(), done: false }); // 更新本地存储数据 setLocalStorage(localDate); // 2. 渲染页面 loadPage(); } // 清空表单的内容 $(this).val(""); } }) // 3. 删除按钮的操做 // 实质是,删除的是本地存储中的数据,再从新渲染页面 $("#todolist,#donelist").on("click", "a", function () { // 获取当前点击的索引号 var index = $(this).attr("id"); console.log(index); // 读取本地存储 var localDate = getLocalStorage(); // 删除对应的数据 splice(删除的其实位置,删除的个数) localDate.splice(index, 1); // 更新本地存储数据 setLocalStorage(localDate); // 从新渲染页面 loadPage(); }) // 4. 点击复选框 匹配状态 // 本质是,点击更改本地存储数据中复选框状态,从新渲染页面 $("#todolist,#donelist").on("click", "input", function () { // 读取本地存储数据 var localDate = getLocalStorage(); // 获取被点击的元素的索引 var index = $(this).siblings("a").attr("id"); // 修改数据 localDate[index].done = $(this).prop("checked"); // 更新本地数据 setLocalStorage(localDate); // 从新渲染页面 loadPage(); }) // 5. 统计个数 —— 渲染页面的时候操做 // 2. 把本地存储数据渲染到页面 function loadPage() { // 2.1 先读取本地存储数据 var date = getLocalStorage(); // 遍历以前先清空页面中的ul和ol的内容 防止后面重复添加 $("#todolist,#donelist").empty(); // 记录已完成和进行中的个数 var toDoCount = 0; var doneCount = 0; // 2.2 遍历本地存储数据 有多少个对象就建立多少个li $.each(date, function (i, ele) { // 根据复选框的状态,决定添加到那个部分 // done为true 加到 donelist中 if (ele.done) { // 自定义属性 id 记录数据在本地存储中的位置 $("#donelist").prepend("<li><input type = 'checkbox' checked><p>" + ele.title + "</p><a href = '#' id=" + i + "></a></li>") // 更新个数 doneCount++; } else { $("#todolist").prepend("<li><input type = 'checkbox'><p>" + ele.title + "</p><a href = '#' id=" + i + "></a></li>") toDoCount++; } }) $("#todocount").text(toDoCount); $("#donecount").text(doneCount); } // 读取本地存储的数据 function getLocalStorage() { var date = localStorage.getItem("toDoList"); // 判断本地存储是否为空 if (date != null) { return JSON.parse(date); } else { return []; // 为空返回空数组 } } // 保存本地存储的数据 function setLocalStorage(date) { localStorage.setItem("toDoList", JSON.stringify(date)); } })
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" /> <title>ToDoList—待办事项列表</title> <link rel="stylesheet" href="css/index.css"> <script src="js/jquery.min.js"></script> <script src="js/todolist.js"></script> </head> <body> <header> <section> <label for="title">ToDoList</label> <input type="text" id="title" name="title" placeholder="添加ToDo" required="required" autocomplete="off" /> </section> </header> <section> <h2>正在进行 <span id="todocount"></span></h2> <ol id="todolist" class="demo-box"> <!-- <li> <input type="checkbox"> <p>123</p> <a href="#"></a> </li> --> </ol> <h2>已经完成 <span id="donecount"></span></h2> <ul id="donelist"> </ul> </section> <footer> Copyright © 2014 todolist.cn </footer> </body> </html>
body { margin: 0; padding: 0; font-size: 16px; background: #CDCDCD; } header { height: 50px; background: #333; background: rgba(47, 47, 47, 0.98); } section { margin: 0 auto; } label { float: left; width: 100px; line-height: 50px; color: #DDD; font-size: 24px; cursor: pointer; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; } header input { float: right; width: 60%; height: 24px; margin-top: 12px; text-indent: 10px; border-radius: 5px; box-shadow: 0 1px 0 rgba(255, 255, 255, 0.24), 0 1px 6px rgba(0, 0, 0, 0.45) inset; border: none } input:focus { outline-width: 0 } h2 { position: relative; } span { position: absolute; top: 2px; right: 5px; display: inline-block; padding: 0 5px; height: 20px; border-radius: 20px; background: #E6E6FA; line-height: 22px; text-align: center; color: #666; font-size: 14px; } ol, ul { padding: 0; list-style: none; } li input { position: absolute; top: 2px; left: 10px; width: 22px; height: 22px; cursor: pointer; } p { margin: 0; } li p input { top: 3px; left: 40px; width: 70%; height: 20px; line-height: 14px; text-indent: 5px; font-size: 14px; } li { position: relative; height: 32px; line-height: 32px; background: #fff; margin-bottom: 10px; padding: 0 45px; border-radius: 3px; border-left: 5px solid #629A9C; box-shadow: 0 1px 2px rgba(0, 0, 0, 0.07); } ol li { cursor: move; } ul li { border-left: 5px solid #999; opacity: 0.5; } li a { position: absolute; top: 2px; right: 5px; display: inline-block; width: 14px; height: 12px; border-radius: 14px; border: 6px double #FFF; background: #CCC; line-height: 14px; text-align: center; color: #FFF; font-weight: bold; font-size: 14px; cursor: pointer; } footer { color: #666; font-size: 14px; text-align: center; } footer a { color: #666; text-decoration: none; color: #999; } @media screen and (max-device-width: 620px) { section { width: 96%; padding: 0 2%; } } @media screen and (min-width: 620px) { section { width: 600px; padding: 0 10px; } }