jQuery模仿ToDoList实现简单的待办事项列表


功能:在文本框中输入待办事项按下回车后,事项会出现在未完成列表中;点击未完成事项前边的复选框后,该事项会出现在已完成列表中,反之亦然;点击删除按钮会删除该事项;双击事项可以修改事项的内容。待办事项的数据是保存到本地存储的(localStorage),就算关闭页面再打开,数据还是存在的(前提是要用相同浏览器)。

ToDoList链接:ToDoList—最简单的待办事项列表

先把css样式以及js文件引入进来,jQuery文件要写在你自己的js文件上边

<link rel="stylesheet" href="css/index.css">
<script src="js/jquery.min.js">script>
<script src="js/todolist.js">script>

HTML代码:

 1 <body>
 2     <header>
 3         <section>
 4             <label for="title">ToDoListlabel>
 5             <input type="text" id="title" name="title" placeholder="添加ToDo" required="required" autocomplete="off" />
 6         section>
 7     header>
 8     <section>
 9         <h2>正在进行 <span id="todocount">span>h2>
10         <ol id="todolist" class="demo-box">
11 
12         ol>
13         <h2>已经完成 <span id="donecount">span>h2>
14         <ul id="donelist">
15 
16         ul>
17     section>
18     <footer>
19         Copyright © 2019 
20     footer>
21 body>
  1 body {
  2     margin: 0;
  3     padding: 0;
  4     font-size: 16px;
  5     background: #CDCDCD;
  6 }
  7 
  8 header {
  9     height: 50px;
 10     background: #333;
 11     background: rgba(47, 47, 47, 0.98);
 12 }
 13 
 14 section {
 15     margin: 0 auto;
 16 }
 17 
 18 label {
 19     float: left;
 20     width: 100px;
 21     line-height: 50px;
 22     color: #DDD;
 23     font-size: 24px;
 24     cursor: pointer;
 25     font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
 26 }
 27 
 28 header input {
 29     float: right;
 30     width: 60%;
 31     height: 24px;
 32     margin-top: 12px;
 33     text-indent: 10px;
 34     border-radius: 5px;
 35     box-shadow: 0 1px 0 rgba(255, 255, 255, 0.24), 0 1px 6px rgba(0, 0, 0, 0.45) inset;
 36     border: none
 37 }
 38 
 39 input:focus {
 40     outline-width: 0
 41 }
 42 
 43 h2 {
 44     position: relative;
 45 }
 46 
 47 span {
 48     position: absolute;
 49     top: 2px;
 50     right: 5px;
 51     display: inline-block;
 52     padding: 0 5px;
 53     height: 20px;
 54     border-radius: 20px;
 55     background: #E6E6FA;
 56     line-height: 22px;
 57     text-align: center;
 58     color: #666;
 59     font-size: 14px;
 60 }
 61 
 62 ol,
 63 ul {
 64     padding: 0;
 65     list-style: none;
 66 }
 67 
 68 li input {
 69     position: absolute;
 70     top: 2px;
 71     left: 10px;
 72     width: 22px;
 73     height: 22px;
 74     cursor: pointer;
 75 }
 76 
 77 p {
 78     margin: 0;
 79 }
 80 
 81 li p input {
 82     top: 3px;
 83     left: 40px;
 84     width: 70%;
 85     height: 20px;
 86     line-height: 14px;
 87     text-indent: 5px;
 88     font-size: 14px;
 89 }
 90 
 91 li {
 92     height: 32px;
 93     line-height: 32px;
 94     background: #fff;
 95     position: relative;
 96     margin-bottom: 10px;
 97     padding: 0 45px;
 98     border-radius: 3px;
 99     border-left: 5px solid #629A9C;
100     box-shadow: 0 1px 2px rgba(0, 0, 0, 0.07);
101 }
102 
103 ol li {
104     cursor: move;
105 }
106 
107 ul li {
108     border-left: 5px solid #999;
109     opacity: 0.5;
110 }
111 
112 li a {
113     position: absolute;
114     top: 2px;
115     right: 5px;
116     display: inline-block;
117     width: 14px;
118     height: 12px;
119     border-radius: 14px;
120     border: 6px double #FFF;
121     background: #CCC;
122     line-height: 14px;
123     text-align: center;
124     color: #FFF;
125     font-weight: bold;
126     font-size: 14px;
127     cursor: pointer;
128 }
129 
130 footer {
131     color: #666;
132     font-size: 14px;
133     text-align: center;
134 }
135 
136 footer a {
137     color: #666;
138     text-decoration: none;
139     color: #999;
140 }
141 
142 @media screen and (max-device-width: 620px) {
143     section {
144         width: 96%;
145         padding: 0 2%;
146     }
147 }
148 
149 @media screen and (min-width: 620px) {
150     section {
151         width: 600px;
152         padding: 0 10px;
153     }
154 }
index.css

接下来开始写我们自己的js代码

将多次使用的代码封装成函数,方便使用

①获取本地存储的数据。如果本地有数据则直接获取过来,没有数据的话就返回一个空数组

1 function getDate() {
2     var data = localStorage.getItem("todolist");   // 将获取到的数据赋给data
3     if(data !== null) {     // 如果本地有数据,则返回数据
4         return JSON.parse(data);  // 本地存储只能存储字符串,所以要想获取里边的数据就必须将字符串转换为数组形式返回
5     } else { 
6         return [];   // 如果本地没有数据,则返回一个空数组
7     }
8 }

②保存本地存储数据

1 function saveDate(data) {
2     // 用JSON.stringify()将数组转化成字符串保存到本地存储
3     localStorage.setItem("todolist", JSON.stringify(data));
4 }

③渲染页面 加载数据

先将本地存储数据获取过来;将他们遍历(遍历之前先将列表清空),看他们是否已经被完成(通过数组里我们自己添加的done的值为true还是false来判断),如果已经被完成则添加到ul列表,否则添加进ol列表里;同时声明两个变量来保存已完成和未完成事项的个数

 1 function load() {
 2     var data = getDate();    // 先获取本地存储数据
 3 
 4     // 遍历本地存储数据 将他们添加到列表中
 5     $("ol, ul").empty();   // 遍历之前先清空列表
 6     var doneCount = 0;  // 已经完成的个数
 7     var todoCount = 0;  // 正在进行的个数
 8     $.each(data, function(i, ele) {    // i为索引 ele为遍历对象
 9         // 如果复选框被选中(已完成done: true)添加到ul里,未被选中(未完成done: false)添加到ol里
10         if(ele.done) {
11             $("ul").prepend("
  • " + ele.title + "

  • "); 12 doneCount++; // 每添加一个li,已完成数加一 13 } else { 14 $("ol").prepend("
  • " + ele.title + "

  • "); 15 todoCount++; 16 } 17 }) 18 $("#donecount").text(doneCount); 19 $("#todocount").text(todoCount); 20 }

    1. 用户输入待办事项按下回车,将事项添加进列表

    给文本框绑定键盘按下事件,通过ASCII值来判断用户是否按下了回车(回车的ASCII值为13);

    不能直接在本地存储里更改数据,所以要先获取数据(数组形式),把数组进行更新数据(把最新数据追加给数组),再保存到本地存储;

    然后对页面进行重新渲染 更新数据

     1 load();   // 第一步先渲染页面,不然一开始刷新页面时列表不显示
     2 $("#title").on("keydown", function(event) {
     3     if(event.keyCode === 13) {
     4         if($(this).val().trim() !== "") {  // trim()去除字符串两侧空格
     5             var data = getDate();       // 获取本地存储数据
     6             // 把数组进行更新数据,把最新数据追加给数组
     7             data.push({title: $(this).val(), done: false});
     8             saveDate(data);      // 保存到本地存储
     9             load();              // 渲染加载到页面
    10             $(this).val("");
    11         }
    12     }
    13 })

    2. 删除待办事项

    先获取本地存储数据;

    用attr获取自定义属性index(索引)得到用户点击的第几个事项,通过索引删除数组里对应的那组数据;

    将更新过的数组保存到本地存储 再渲染给页面

    1 $("ol, ul").on("click", "a", function() {
    2     var data = getDate();    // 获取本地数据(data是局部变量,不用担心冲突)
    3     var index = $(this).attr("index");   // 用attr获取自定义属性index,得到索引
    4     // splice(index, num)删除数组对象  index为开始删除的位置,num为删除几个
    5     data.splice(index, 1);
    6     saveDate(data);
    7     load();
    8 })

    3. 用户点击复选框来选择事项已完成或未完成

    获取本地存储数据;

    通过复选框的兄弟a的index属性来获取用户点击的事项的索引(index),将第index个数据的done属性值修改为复选框的值;

    将更新过的数组保存到本地存储 再渲染给页面

    1 $("ol, ul").on("click", "input", function() {
    2     var data = getDate();
    3     // 利用a获取用户点击的第几个复选框
    4     var index = $(this).siblings("a").attr("index");
    5     // 修改数据:data[索引].属性名  获取固有属性用prop
    6     data[index].done = $(this).prop("checked");
    7     saveDate(data);
    8     load();
    9 })

     4. 用户可以通过双击事项进行修改

    获取本地存储数据;通过a获取索引index;

    在p里创建一个文本框,把p原来的内容赋给文本框,并让其为选中状态;

    当文本框失去焦点或用户点击回车,将修改后的内容给当前数组对象的title属性;

    将更新过的数组保存到本地存储 再渲染给页面

     1 $("ol, ul").on("dblclick", "p", function() {
     2     var data = getDate();
     3     var index = $(this).siblings("a").attr("index");
     4     // 先将p原来的内容获取过来
     5     var str = $(this).text();
     6     // 创建一个文本框,直接添加到p里
     7     $(this).prepend('');
     8     // 将原来内容给文本框,并让其为选中(select)状态
     9     var input = $(this).children();
    10     input.val(str);
    11     input.select();
    12     // 当文本框失去焦点,将修改过的文本框的内容给title
    13     $(input).on("blur", function() {
    14         data[index].title = input.val();
    15         saveDate(data);
    16         load();
    17     })
    18     // 按下回车时保存修改
    19     $(input).on("keyup", function(e) {
    20         if(e.keyCode === 13) {   // 回车ASCII值为13
    21             // 手动调用点击事件
    22             this.blur();
    23         }
    24     })
    25 })

    详细JS代码:

     1 $(function() {
     2     load();   // 第一步先渲染页面,不然一开始刷新页面时列表不显示
     3     // 1、给文本框绑定键盘按下事件
     4     $("#title").on("keydown", function(event) {
     5         if(event.keyCode === 13) {
     6             if($(this).val().trim() !== "") {  // trim()去除字符串两侧空格
     7                 var data = getDate();       // 获取本地存储数据
     8                 // 把数组进行更新数据,把最新数据追加给数组
     9                 data.push({title: $(this).val(), done: false});
    10                 saveDate(data);      // 保存到本地存储
    11                 load();              // 渲染加载到页面
    12                 $(this).val("");
    13             }
    14         }
    15     })
    16     //2、删除待办事项
    17     $("ol, ul").on("click", "a", function() {
    18         var data = getDate();    // 获取本地数据(data是局部变量,不用担心冲突)
    19         var index = $(this).attr("index");   // 用attr获取自定义属性index,得到索引
    20         // splice(index, num)删除数组对象  index为开始删除的位置,num为删除几个
    21         data.splice(index, 1);
    22         saveDate(data);
    23         load();
    24     })
    25     //3、正在进行和已完成
    26     $("ol, ul").on("click", "input", function() {
    27         var data = getDate();
    28         // 利用a获取用户点击的第几个复选框
    29         var index = $(this).siblings("a").attr("index");
    30         // 修改数据:data[索引].属性名  获取固有属性用prop
    31         data[index].done = $(this).prop("checked");
    32         saveDate(data);
    33         load();
    34     })
    35     // 4、修改事项
    36     $("ol, ul").on("dblclick", "p", function() {
    37         var data = getDate();
    38         var index = $(this).siblings("a").attr("index");
    39         // 先将p原来的内容获取过来
    40         var str = $(this).text();
    41         // 创建一个文本框,直接添加到p里
    42         $(this).prepend('');
    43         // 将原来内容给文本框,并让其为选中(select)状态
    44         var input = $(this).children();
    45         input.val(str);
    46         input.select();
    47         // 当文本框失去焦点,将修改过的文本框的内容给title
    48         $(input).on("blur", function() {
    49             data[index].title = input.val();
    50             saveDate(data);
    51             load();
    52         })
    53         // 按下回车也可以保存修改
    54         $(input).on("keyup", function(e) {
    55             if(e.keyCode === 13) {   // 回车ASCII值为13
    56                 // 手动调用点击事件
    57                 this.blur();
    58             }
    59         })
    60     })
    61     // 获取本地存储数据
    62     function getDate() {
    63         var data = localStorage.getItem("todolist");   // 将获取到的数据赋给data
    64         if(data !== null) {     // 如果本地有数据,则返回数据
    65             return JSON.parse(data);  // 本地存储只能存储字符串,所以要获取里边的数据就必须将字符串转换为数组形式返回
    66         } else { 
    67             return [];   // 如果本地没有数据,则返回一个空数组
    68         }
    69     }
    70     // 保存本地存储数据
    71     function saveDate(data) {
    72         // 用JSON.stringify()将数组转化成字符串保存到本地存储
    73         localStorage.setItem("todolist", JSON.stringify(data));
    74     }
    75     // 渲染加载数据
    76     function load() {
    77         var data = getDate();    // 先获取本地存储数据
    78 
    79         // 遍历本地存储数据 将他们添加到列表中
    80         $("ol, ul").empty();   // 遍历之前先清空列表
    81         var doneCount = 0;  // 已经完成的个数
    82         var todoCount = 0;  // 正在进行的个数
    83         $.each(data, function(i, ele) {    // i为索引 ele为遍历对象
    84             // 如果复选框被选中(已完成done: true)添加到ul里,未被选中(未完成done: false)添加到ol里
    85             if(ele.done) {
    86                 $("ul").prepend("
  • " + ele.title + "

  • "); 87 doneCount++; // 每添加一个li,已完成数加一 88 } else { 89 $("ol").prepend("
  • " + ele.title + "

  • "); 90 todoCount++; 91 } 92 }) 93 $("#donecount").text(doneCount); 94 $("#todocount").text(todoCount); 95 } 96 })

    具体代码点击→https://github.com/sunyan1998/Some-demos (觉得不错右上角顺手点个star哦~感谢O(∩_∩)O~)

    里面有很多CSS3/JS/jQuery小例子哦,包括各种轮播图、电梯导航、封装的动画函数、todolist、登录模态框(可拖动)、购物车、点击换肤、密码显示隐藏、各种布局(bootstrap-flex-rem)等等......