作者:©Iaine 万一
简介:30 Day Challenge是 Wes Bos 设计的一个 30 天原生js编程挑战。项目免费提供了 30 个视频教程、30 个挑战的起始文档和 30 个挑战解决方案源代码。本项目为第15天的“JS window属性: localStorage ”项目。Have fun with the website! ♪(^∇^*)
网页效果: https://janice143.github.io/localStorage/
项目描述
本项目是一个可添加项目的点菜清单,刷新网页时,菜单信息不会清空。实现该功能的主要技术是JavaScript Window 对象的localStorage属性。
项目重点
-
localStorage.setItem
localStorage.getItem
JS取消默认行为
reset() 方法
- 把表单中的元素重置为默认值
JSON 的方法
JSON.stringify
JSON.parse
项目过程
HTML部分
网页logo
<svg>
标签
菜品清单内容
标题
<h2>
菜单项目
<ul>
添加菜品表单
<form>
1
2
3
4
5
6
7
8
9
10
11<div class="wrapper">
<h2>LOCAL TAPAS</h2>
<p></p>
<ul class="plates">
<li>Loading Tapas...</li>
</ul>
<form class="add-items">
<input type="text" name="item" placeholder="Item Name" required>
<input type="submit" value="+ Add Item">
</form>
</div>
CSS部分
菜品项目添加后默认复选框⬜️没有checked
1
2
3
4.plates input + label:before {
content: "⬜️";
margin-right: 10px;
}菜品项目checked后方框变成其他图标
1
2
3.plates input:checked + label:before {
content: "🌮";
}
JS部分
form表单中若有type 属性是 “submit”的元素,则具有
submit
事件1
2
3
4function addItem(){
console.log('hello')
}
addItems.addEventListener('submit', addItem);当点击form中的提交按钮时,会提交表单并且刷新页面(可在控制台中看出闪现hello),这种默认行为可以通过 e.preventDefault来阻止
1
2
3function addItem(e){
e.preventDefault();
}下面开始正式编写addItem函数,用来获取form中添加的元素,然后放到items变量中存储起来
this.querySelector('[name=item]')
选择type为text元素的值(输入框输入的内容)- 构造一个对象 item 来存储这个信息
- 把item push到提前创建的items(所有菜单)中
1
2
3
4
5
6
7const text = (this.querySelector('[name=item]')).value;
// 构造一个对象 item 来存储这个信息
item = {
text, // ES6中对 text: text, 的简写
done:false // 标记有没有checked
}
items.push(item);- 执行populateList(items, itemsList)函数,把新添加的菜品显示到页面中
- 更新localStorage中的items数据
- 重置输入框的值
1
2
3populateList(items, itemsList);
localStorage.setItem('items', JSON.stringify(items));
this.reset();编写populateList函数,实现将items中的信息挂载到DOM树上
<input>
标签实现的复选框data-index
属性标记菜品序号
<label>
标签记录菜单的文字
1 | function populateList(plates = [], platesList) { |
程序写到这里基本完成,但是仔细观察会发现,如果checked每个菜品,刷新页面后,这个状态会被刷新(不被保留),这是因为我们并没有更新items中done的值
所以还需编写toggleDone函数,通过菜品click事件触发
e.target.dataset.index
可以获取利用data-index
属性标记菜品序号!items[index].done
否操作- 更新localStorage和HTML页面
1
2
3
4
5
6
7
8
9
10function toggleDone(e) {
if (!e.target.matches('input')) return; // skip this unless it's an input
// console.log(e.target)
const el = e.target;
const index = el.dataset.index;
items[index].done = !items[index].done;
localStorage.setItem('items', JSON.stringify(items));
populateList(items, itemsList);
}
itemsList.addEventListener('click', toggleDone);
项目补充
HTML <input>
标签的 required 属性
required 属性规定必需在提交之前填写输入字段
JS-preventDefault() 取消默认行为
语法:event.preventDefault()
该方法将通知 Web 浏览器不要执行与事件关联的默认动作(如果存在这样的动作)。
常用情景:
- 如果 type 属性是 “submit”,在事件传播的任意阶段可以调用任意的事件句柄,通过调用该方法,可以阻止提交表单。
- a 标签点击时,会跳转url,采用如下方式,可防止链接打开 URL:
常用情景的知识点来源于博客
JSON.parse和JSON.stringify
JSON对象在所有现代浏览器中都适用,他有两个非常有用的方法是parse()和stringify().
JSON.parse()
把一个JSON字符串转变成JS对象
1 | let userStr = '{"name":"Sammy","email":"[email protected]","plan":"Pro"}'; |
JSON.parse()
第二个参数可以是一个自定义函数,具有返回值
1 | let userStr = '{"name":"Sammy","email":"[email protected]","plan":"Pro"}'; |
JSON.stringify()
把一个JS对象转变成JSON字符串
1 | let userObj = { |
JSON.stringify()可以有两个额外参数
- 一个replacer参数(是一个自定义函数,函数名为replacer)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15let userObj = {
name: "Sammy",
email: "[email protected]",
plan: "Pro"
};
function replacer(key, value) {
console.log(typeof value);
if (key === 'email') {
return undefined;
}
return value;
}
let userStrReplacer = JSON.stringify(userObj, replacer);
console.log(userStrReplacer);
// {"name":"Sammy","plan":"Pro"}- 一个是space参数(是
String
或者Number
值),用来控制间距- 如果是Number,缩进为空格数(1-10)
- 如果是String,缩进为该字符串
1
2
3
4
5
6JSON.stringify({ uno: 1, dos: 2 }, null, '\t');
// returns the string:
// '{
// "uno": 1,
// "dos": 2
// }'
map()和forEach()的区别和理解
两个方法都可以实现元素遍历,但是map方法可以用返回值,而forEach方法没有返回值
参考博客
- JS-preventDefault() 取消默认行为
- How To Use JSON.parse() and JSON.stringify()
- Example of using JSON.stringify() with localStorage
- map()和forEach()的区别和理解
JS30的第15个项目圆满完成啦,感谢阅读,有问题联系我的邮箱[email protected].