第15天的內(nèi)容是類似一個(gè)todolist
把內(nèi)容存到localStorage里防止每次打開就沒有之前的內(nèi)容
js腳本內(nèi)嵌在html里,css寫在另一個(gè)文件里
HTML
寫了一個(gè)logo放在上面
下面一個(gè)div里放著列表、輸入框和提交按鈕
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>LocalStorage</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<!-- 用了張本地照片作為logo -->
<img src="/15 - LocalStorage/logo.jpg" alt="" class="logo">
<div class="wrapper">
<h2>To Do It</h2>
<p></p>
<ul class="plates">
<li>Loading...</li>
</ul>
<form class="add-items">
<input type="text" name="item" placeholder="Item Name" required>
<input type="submit" value=" -Add Item- ">
</form>
<p class="clear">clear all</p>
</div>
</body>
</html>
這個(gè)不是重點(diǎn)
JavaScript
如果不考慮list內(nèi)容需不需要checked,只需要一個(gè)列表的話
只要addItem和populateList函數(shù)就夠了,然后加個(gè)監(jiān)聽
toggleDone是為了刷新是否checked,還加了個(gè)clear的監(jiān)聽
<script>
//選取頁面內(nèi)容
const addItems = document.querySelector('.add-items');
const itemsList = document.querySelector('.plates');
const clear_ = document.querySelector('.clear');
//從緩存拿數(shù)組數(shù)據(jù)或新建數(shù)組
var items = JSON.parse(localStorage.getItem('items')) ||[];
//addItem函數(shù)用于將輸入框內(nèi)容添加到數(shù)組里
function addItem(e){
//這個(gè)preventDefault()是為了防止自動(dòng)刷新
e.preventDefault();
const text = this.querySelector('[name=item]').value;
const item = {text:text , checked :false};
items.push(item);
this.reset();
populateList(items,itemsList);
localStorage.setItem('items',JSON.stringify(items));
}
//populateList用于添加內(nèi)容到html里
function populateList(plates = [],plateslist){
plateslist.innerHTML = plates.map((plate,i) =>{
return `
<li>
<input type = 'checkbox' data-index=${i} id = "item${i}" ${plate.checked ? 'checked' : ''} >
<label for="item${i}"> ${plate.text} </label>
</li>
`;
}).join('');
}
//toggleDone是用于刷新緩存里的item是否完成選項(xiàng)
function toggleDone(e){
if (!e.target.matches('input')) return;
items[e.target.dataset.index].checked = !items[e.target.dataset.index].checked;
localStorage.setItem('items', JSON.stringify(items));
}
//添加監(jiān)聽
addItems.addEventListener('submit',addItem);
itemsList.addEventListener('click',toggleDone);
clear_.addEventListener('click',()=>{
items = [];
populateList(items, itemsList);
localStorage.setItem('items', JSON.stringify(items));
});
//第一次運(yùn)行刷新items
populateList(items,itemsList);
</script>
用到的函數(shù)
- Array.map() 返回一個(gè)新數(shù)組
- Array.push() 將內(nèi)容添加到數(shù)組里
- JSON 一個(gè)數(shù)據(jù)儲(chǔ)存與讀取庫,可以按一定的規(guī)則存儲(chǔ)數(shù)據(jù)
- JSON.Stringfy() 將數(shù)組轉(zhuǎn)化為JSON格式String
- JSON.parse() 還原JSON字符串為數(shù)組或字典
- preventDefault() 阻止自帶函數(shù)
討論
實(shí)現(xiàn)目標(biāo)效果不是很難,或者說比我想象的簡(jiǎn)單一點(diǎn),但用localStorage總覺得有點(diǎn)問題。
如果是服務(wù)端的話,那應(yīng)該會(huì)在服務(wù)器哪里存著,然后根據(jù)http請(qǐng)求的頭文件找對(duì)應(yīng)文件。
css部分覺得難搞多了,給input按鈕加了個(gè):hover和:actice,果然使用體驗(yàn)好多了,沒有反饋的交互按鍵真是不合理的東西。
CSS源碼
html {
box-sizing: border-box;
background:url('/15\ -\ LocalStorage/photo-1551300444-2a7ea9b69f2e.jpg') center no-repeat;
background-size:cover;
/* min-height:100vh;*/
display:flex;
justify-content: center;
/* align-items: center; */
text-align: center;
font-family: Futura,"Trebuchet MS",Arial,sans-serif
}
*, *:before, *:after {box-sizing: inherit; }
img {
fill:white;
background: rgba(255,255,255,0.4);
padding: 20px;
border-radius: 50%;
width:150px;
margin-bottom: 20px;
}
.wrapper {
padding: 20px;
max-width: 350px;
background: rgba(255,255,255,0.95);
box-shadow: 0 0 0 10px rgba(0,0,0,0.1);
padding-bottom: 5px;
}
h2 {
text-align: center;
margin: 0;
font-weight: 200;
}
.plates {
margin: 0;
padding: 0;
text-align: left;
list-style: none;
}
.plates li {
border-bottom: 1px solid rgba(0,0,0,0.2);
padding: 10px 0;
font-weight: 100;
display: flex;
}
.plates label {
flex:1;
cursor: pointer;
}
.plates input {
display: none;
}
.plates input + label:before {
content: '??';
margin-right: 10px;
}
.plates input:checked + label:before {
content: '??';
}
.add-items {
margin-top: 20px;
}
.add-items input {
padding:8px;
padding-left: 12px;
padding-right: 12px;
outline:0;
border:1px solid rgba(0,0,0,0.1);
margin-left: 10px;
border-radius: 20px;
cursor: pointer;
box-shadow: 2px 2px 1px rgba(0,0,0,0.1);
text-shadow: 1px 1px 2px rgba(0,0,0,.2);
}
.add-items input:hover{
background-color: #81ecec;
}
.add-items input:active{
background-color: #0984e3;
}
.add-items input[type=text] {
border-radius: 12px;
cursor: text;
}
.add-items input[type=text]:hover {
background-color: #fff;
}
.clear{
margin-top: 10px;
margin-bottom: 10px;
width: 60px;
color: #b2bec3;
margin-left: auto;
margin-right: auto;
}
.clear:hover{
cursor: pointer;
}
.clear:active{
color: #0984e3;
}
body{
margin-top: 100px;
}