todolist的例子(利用本地存储)
结合rem布局和本地存储编写一个具有记录日程的程序。利用rem布局使得页面适用于各种设备类型。
需求
1、移动端为主Pc端可用
2、输入框,输入待办事项
3、未完成列表能够显示出未完成的内容,可以对其删除,改成完成状态
4、完成列表:能够显示完成内容,可以删除改成未完成
步骤:
html结构、
css样式、
javascript功能:
输入框
未完成、完成列表显示
删除改变状态功能
首先搭建基于rem布局的页面框架
style.css
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
body{
background-color: #efefef;
font-size: 16px;
}
.main{
width: 3.75rem;
}
.header{
width: 3.75rem;
height: 0.5rem;
background: cornflowerblue;
display: flex;
justify-content: space-between;
align-items: center;
position: relative;
}
.header>.logo{
width: 1rem;
height: 0.5rem;
line-height: 0.5rem;
text-align: center;
font-size: 0.2rem;
font-weight: 700;
position: absolute;
left: 0.2rem;
}
.header>input{
height: 0.3rem;
width: 2rem;
position: absolute;
right: 0.2rem;
border-radius: 0.05rem;
border: none;
outline: none;
padding: 0 0.1rem;
}
.todo h3{
height: 0.6rem;
line-height: 0.6rem;
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 0.15rem;
}
.todo .list{
padding: 0 0.15rem;
}
.todo .todoItem{
display: flex;
height: 0.32rem;
line-height: 0.38rem;
align-items: center;
background: lightblue;
border-radius: 0.03rem;
overflow: hidden;
margin-bottom: 0.1rem;
}
.todo .todoItem>input{
width: 0.2rem;
height: 0.2rem;
margin: 0 0.1rem;
}
.todo .todoItem .content{
width: 2.65rem;
color:#333 ;
}
.todo .todoItem:before{
width: 0.04rem;
height: 100%;
background: #6495ED;
content: ""; /* 不加没有效果 */
}
.todo .todoItem .del{
background: #ccc;
width: 0.4rem;
height: 0.2rem;
font-size: 0.3rem;
font-weight: 600;
text-align: center;
line-height: 0.2rem;
border-radius: 0.15rem;
margin: 0 0.1rem;
}
.done .todoItem{
opacity: 0.5;
/* -webkit-filter: grayscale(0.5); */
}
.pc{
font-size: 200px !important;
}
.pc .main{
margin: 0 auto;
}
rem布局辅助js:
(function(){
function xys(){
var userAgent=navigator.userAgent
var html=document.querySelector("html");
//userAgent.indexOf("iPhone")通过此方法可以获取iPhone在字符串中的索引值(开头位置)
//没有找到返回-1
html.className="";
if((userAgent.indexOf("iPhone"))!=-1){
html.classList.add("iphone");
}else if((userAgent.indexOf("Android"))!=-1)
{
html.classList.add("android");
}else if((userAgent.indexOf("iPad"))!=-1){
html.classList.add("ipad");
}else{
html.classList.add("pc");
}
if(window.innerWidth<640){
html.classList.add('lt640');
html.classList.add('lt960');
html.classList.add('lt1200');
}else if(window.innerWidth<960){
html.classList.add('lt960');
html.classList.add('lt1200');
html.classList.add('gt640');
}else if(window.innerWidth<1200){
html.classList.add('lt1200');
html.classList.add('gt640');
html.classList.add('gt960');
}else{
html.classList.add('gt640');
html.classList.add('gt960');
html.classList.add('gt1200');
}
var screenWidth=window.innerWidth;
var danwei=screenWidth/3.75;//屏幕的宽度/设计稿占满全屏的宽度为多少rem
var html=document.querySelector("html")
html.style.fontSize=danwei+"px";
}
xys();
window.onresize=function(){
xys();
}
})()
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
<script src="js/js辅助式响应.js" type="text/javascript" charset="utf-8"></script>
<link rel="stylesheet" type="text/css" href="css/style.css"/>
</head>
<body>
<!-- .main>((.header>(.logo{todologo}+input))+(.doing>(h3>(span.title{正在进行})+span.num)+.list)+(.done>(h3>(span.title{已完成})+span.num)+.list)) -->
<div class="main">
<div class="header">
<div class="logo">todologo</div>
<input type="text" placeholder="请输入待办事项"/>
</div>
<div class="doing todo">
<h3>
<span class="title">正在进行</span>
<span class="num">0</span>
</h3>
<div class="list">
<!-- .todoItem>(input+.content+.del) -->
<div class="todoItem">
<input type="checkbox">
<div class="content">熬夜</div>
<div class="del">-</div>
</div>
</div>
</div>
<div class="done todo">
<h3>
<span class="title">已完成</span>
<span class="num">0</span>
</h3>
<div class="list">
<div class="todoItem">
<input type="checkbox">
<div class="content">熬夜</div>
<div class="del">-</div>
</div>
</div>
</div>
</div>
</body>
</html>
初始效果:
最终版本:主要加入了Js语句实现了各种功能。打开页面进行渲染,获取本地存储中的todolist数组,每次输入事项回车时重新进行渲染。每次渲染时都存入当前的数组的状态。
这次案例中值得注意的有
- Json格式和对象格式的来回转换,存储到本地存储时,利用JSON.stringify(todoList),存入json格式的字符串。当获取本地存储的数组时利用JSON.parse(localStorage.todoList)将json格式字符串转化为对象。
- 注意函数中的event对象的target属性,比如这次的删除操作是在整体div的点击事件中利用e.target.className判读点击的是哪个div。只有点击del的div时才进行删除操作。
- data-index="${index}在为了在每一个事项列表中绑定复选框、删除div和每个事项在todolist中的索引值,而新加入的属性。此属性可以通过event.target.dataset.index获取
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
<script src="js/js辅助式响应.js" type="text/javascript" charset="utf-8"></script>
<link rel="stylesheet" type="text/css" href="css/style.css"/>
</head>
<body>
//<!-- .main>((.header>(.logo{todologo}+input))+(.doing>(h3>(span.title{正在进行})+span.num)+.list)+(.done>(h3>(span.title{已完成})+span.num)+.list)) -->
<div class="main">
<div class="header">
<div class="logo">todologo</div>
<input id="input" type="text" placeholder="请输入待办事项"/>
</div>
<div class="doing todo">
<h3>
<span class="title">正在进行</span>
<span class="num">0</span>
</h3>
<div class="list">
//<!-- .todoItem>(input+.content+.del) -->
</div>
</div>
<div class="done todo">
<h3>
<span class="title">已完成</span>
<span class="num">0</span>
</h3>
<div class="list">
</div>
</div>
</div>
<script type="text/javascript">
var todoList;
//数组存储
if(localStorage.todoList==undefined){
todoList=[];
}else{
//将json格式字符串转化为对象
todoList=JSON.parse(localStorage.todoList);
}
//获取doing的list对象
var doinglist=document.querySelector(".doing .list")
//获取done的list对象
var donelist=document.querySelector(".done .list")
//获取输入框对象
var inputDom=document.querySelector("#input")
var main=document.querySelector(".main");
inputDom.onkeydown=function(event){
//按下回车键时,获取输入框内容,并且生成未完成列表
if(event.key=="Enter"){
var value=inputDom.value;
var Item={
content:value,
isDone:false
}
todoList.push(Item);
render(todoList);
}
}
function render(todoList){
var doingnum=0;//正在完成的数量
var donenum=0;//已经完成的数量
var doingnumDiv=document.querySelector(".doing .num");
var donenumDiv=document.querySelector(".done .num");
//不能用localStorage.todoList=todoList存,会存入[object,object]
//使用下列方法,将对象转化为json格式的字符串
localStorage.todoList=JSON.stringify(todoList);
//渲染前清空
doinglist.innerHTML="";
donelist.innerHTML="";
todoList.forEach(function(item,index){
var todoItem=document.createElement("div");
todoItem.className="todoItem"
if(item.isDone){
todoItem.innerHTML=`
<input type="checkbox" checked="checked" data-index="${index}">
<div class="content">`+item.content+`</div>
<div class="del" data-index="${index}">-</div`;
donelist.appendChild(todoItem);
donenum++;
}else{
todoItem.innerHTML=`
<input type="checkbox" data-index="${index}">
<div class="content">`+item.content+`</div>
<div class="del" data-index="${index}">-</div`;
doinglist.appendChild(todoItem);
doingnum++;
}
})
doingnumDiv.innerHTML=doingnum;
donenumDiv.innerHTML=donenum;
}
render(todoList);
//当改变正在完成的列表中,某一项的状态时
doinglist.onchange=function(event){
var index=parseInt(event.target.dataset.index);
todoList[index].isDone=true;
render(todoList);
}
//当改变已经完成的列表中,某一项的状态时
donelist.onchange=function(event){
var index=parseInt(event.target.dataset.index);
todoList[index].isDone=false;
render(todoList);
}
//删除操作
main.onclick=function(e){
if(e.target.className=="del"){
var index=parseInt(event.target.dataset.index);
todoList.splice(index,1);
render(todoList);
}
}
</script>
</body>
</html>
最终效果: