目录
1 功能
在文本框中输入内容,然后按下回车,会将内容添加到正在进行中
如果头部的checkbox是被勾选的状态,该条就会到已经完成的下方
点击条目后面的圆按钮,会将该条删除
写入的内容在关闭浏览器后再次访问,之前写的内容不会消失
2 结构与样式
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="css/initialization.css">
<link rel="stylesheet" href="css/index.css">
</head>
<body>
<header>
<div class="container">
<span>ToDoList</span>
<input type="text" placeholder="添加ToDo" maxlength="20">
</div>
</header>
<section class="doing">
<div class="container">
<div class="doing_header">
<h1>正在进行</h1>
<div class="doing_num">0</div>
</div>
<div class="doing_content">
<!-- <div class="doing_line">
<div class="left_color"></div>
<input type="checkbox">
<span>1</span>
<button>
<div></div>
</button>
</div> -->
</div>
</div>
</section>
<section class="done">
<div class="container">
<div class="done_header">
<h1>已经完成</h1>
<div class="done_num">0</div>
</div>
<div class="done_content">
<!-- <div class="done_line">
<div class="left_color"></div>
<input type="checkbox" checked="checked">
<span>1</span>
<button>
<div></div>
</button>
</div> -->
</div>
</div>
</section>
</body>
<script src="../jquery-3.6.1.min.js"></script>
<script src="js/index.js"></script>
</html>
css
body {
// height:3000px;
background-color: rgb(204,205,204);
header {
width: 100%;
height:50px;
background-color: rgb(48,49,48);
.container {
max-width:600px;
margin:0 auto;
span {
float:left;
color: #DDD;
font-size:24px;
line-height: 50px;
}
input {
float: right;
width:60%;
height:24px;
margin-top:12px;
text-indent: 10px;
border-radius: 5px;
box-shadow: 0 1px 0 rgb(255 255 255 / 24%), 0 1px 6px rgb(0 0 0 / 45%) inset;
}
}
}
.doing {
.container {
max-width:600px;
margin:0 auto;
.doing_header {
display: flex;
justify-content: space-between;
margin-top:20px;
h1 {
display: inline-block;
font-size: 25px;
font-weight: bold;
color:rgb(0,0,0)
}
.doing_num {
width:30px;
height:20px;
color:rgb(102,102,126);
font-weight: bold;
text-align: center;
line-height: 20px;
font-size:14px;
border-radius: 10px;
background-color: rgb(230,230,250);
}
}
.doing_content {
width:100%;
margin-top: 20px;
.doing_line {
position: relative;
width: 100%;
height:32px;
border-radius: 5px;
background-color: rgb(255,255,255);
overflow: hidden;
margin-top: 10px;
.left_color {
display: inline-block;
width:5px;
height:100%;
background-color: rgb(98,154,156);
}
input {
position: absolute;
top:5px;
left:20px;
width:22px;
height:22px;
}
span {
position:absolute;
left:50px;
font-size:18px;
line-height: 32px;
color:rgb(0,0,0)
}
button {
position: absolute;
top:3px;
right:5px;
width:26px;
height:24px;
border:3px solid rgb(204,204,204);
border-radius: 50%;
background-color: transparent;
div {
position: absolute;
left: 50%;
top:50%;
transform: translate(-50%,-50%);
width:14px;
height:12px;
border-radius: 50%;
background-color: rgb(204,204,204);
}
}
}
}
}
}
.done {
.container {
max-width:600px;
margin:0 auto;
.done_header {
display: flex;
justify-content: space-between;
margin-top:20px;
h1 {
display: inline-block;
font-size: 25px;
font-weight: bold;
color:rgb(0,0,0)
}
.done_num {
width:30px;
height:20px;
color:rgb(102,102,126);
font-weight: bold;
text-align: center;
line-height: 20px;
font-size:14px;
border-radius: 10px;
background-color: rgb(230,230,250);
}
}
.done_content {
width:100%;
margin-top: 20px;
.done_line {
position: relative;
width: 100%;
height:32px;
border-radius: 5px;
background-color: rgb(237,237,237);
overflow: hidden;
margin-top: 10px;
opacity: 0.5;
.left_color {
display: inline-block;
width:5px;
height:100%;
background-color: #999;
}
input {
position: absolute;
top:5px;
left:20px;
width:22px;
height:22px;
}
span {
position:absolute;
left:50px;
font-size:18px;
line-height: 32px;
color:rgb(0,0,0)
}
button {
position: absolute;
top:3px;
right:5px;
width:26px;
height:24px;
border:3px solid rgb(204,204,204);
border-radius: 50%;
background-color: transparent;
div {
position: absolute;
left: 50%;
top:50%;
transform: translate(-50%,-50%);
width:14px;
height:12px;
border-radius: 50%;
background-color: rgb(204,204,204);
}
}
}
}
}
}
}
虽然打开的时候是这样的
还是要在早期把样式搞定,省的后面麻烦
3 JS部分
load()
function getDate() {
var data = localStorage.getItem("todolist");
if (data !== null) {
return JSON.parse(data);
} else {
return [];
}
}
function saveDate(data) {
localStorage.setItem("todolist", JSON.stringify(data));
}
function load() {
var data = getDate();
$(".done_content,.doing_content").empty();
var doingCount = 0;
var doneCount = 0;
$.each(data, function(index, content) {
if (content.done) {
$(".done_content").prepend('<div class="done_line" index='+index+'><div class="left_color"></div><input type="checkbox" checked="checked"><span>'+content.content+'</span><button><div></div></button></div>');
doneCount = doneCount + 1;
}
else {
$(".doing_content").prepend('<div class="doing_line" index='+index+'><div class="left_color"></div><input type="checkbox"><span>'+content.content+'</span><button><div></div></button></div>');
doingCount = doingCount + 1;
}
}
)
$('.doing_num').text(doingCount)
$('.done_num').text(doneCount)
};
$('header .container input').on('keydown',function(e) {
if (e.keyCode == 13) {
if ($(this).val()) {
data = getDate()
data.push({content:$(this).val(),done:false})
saveDate(data)
$(this).val('')
load()
}
}
})
$('.doing_content,.done_content').on('click','button',function() {
data = getDate()
data.splice($(this).parent()[0].getAttribute('index'),1)
saveDate(data)
load()
})
$('.doing_content,.done_content').on('click','input[type="checkbox"]',function() {
data = getDate()
data[$(this).parent()[0].getAttribute('index')].done = $(this).prop("checked")
saveDate(data)
load()
})
关闭页面数据仍然不消失应该用localStorage,如果使用sessionStorage关闭浏览器后数据会消失。
存储信息的方式是这样的,首先搞一个数组,里面放若干对象,对象的属性content是条目的内容,属性done的值为布尔值,如果为true就表示做完了,放在已经完成中,如果为false就表示没做完,放在正在进行中
本地存储只能储存字符串,所以会用到下面两个方法
- JS变量 = JSON.parse(JSON字符串) 将JSON字符串转变为JS变量
- JSON字符串 = JSON.stringify(JS变量) 将JS变量转变为JSON字符串
JSON不仅仅使用于本地存储,在与后端的交互中也比较常用
3.1 定义读取本地存储数据函数
先声明一个变量去拿键todolist的值,如果拿到了就将data转换为JS变量然后返回,如果拿不到就返回一个空数组
3.2 定义保存本地存储数据函数
将JS变量转换为字符串,然后存到键为todolist的对象中
3.3 定义渲染页面函数
- 后面太长了就截不全了
- 首先读取存储好的todolist内容
- 将之前的正在进行的任务与完成的任务清空,因为我们后面要重新加载一遍,如果不清空就重复了
- 定义正在进行的任务数与已完成的任务数起始值为0
- 遍历读取到的数据,数据我们之前存储的形式是数组里面有若干个对象
- 判断done属性的内容,如果为true就是已完成,生成已完成的元素到已完成中,然后已完成数量+1。这里后面的一堆HTML直接复制的HTML结构中的,加了两个属性,一个是index,给一个索引,让后面删和改的时候好处理,另一个是content,这个内容
- 如果为False就是未完成,与已完成的样式除了CSS不同之外,已完成中的input有checked="checked",未完成中没有(不让其自动勾选)
定义完load()函数后,在开始就使用一遍load()函数,将过往存储的信息加载一遍
3.4 输入功能
使用键盘按下事件,如果按下了回车(keyCode == 13,按回车使用key的字符就不方便了(比如按下e键就写e),也不用特意记录,每次用的时候console.log(e.keyCode)就行了),如果按下回车的时候内容不为空就进行下面的操作,首先获取一遍本地存储的数据,然后再数据的最后的位置加入一条新数据,由于你在文本框中输入的内容都会放在正在进行中,所以done直接给false就行,然后保存数据,将input内容清空,然后加载数据
push()和下面将要提到的splice()都是JS远程数组的内置方法,详细使用方式可以看一下这个 10. 数组 Array_Suyuoa的博客-CSDN博客_js 数组中是否存在某个元素
3.5 删除功能
在这里一定要用on的selector参数绑定事件,只有这样才能给不存在的元素绑定事件
- on绑定可以给未生成的元素绑定,前提是使用on的对象不能是新生成的
先读取,再删除,之后存,存完了加载
3.6 切换任务的状态
如果是已完成的任务点前面的checkbox会变成未完成,如果是未完成的任务点前面的checkbox会变成已完成
逻辑相似,先拿数据,再改数据,然后存数据,最后加载页面
prop()是jQuery中的获取固有属性值的方法,在这里面有介绍 6.jQuery常用属性操作_Suyuoa的博客-CSDN博客