|
4 | 4 | > 简介:[JavaScript30](https://javascript30.com) 是 [Wes Bos](https://github.com/wesbos) 推出的一个 30 天挑战。项目免费提供了 30 个视频教程、30 个挑战的起始文档和 30 个挑战解决方案源代码。目的是帮助人们用纯 JavaScript 来写东西,不借助框架和库,也不使用编译器和引用。现在你看到的是这系列指南的第 15 篇。完整指南在 [GitHub](https://github.com/soyaine/JavaScript30),喜欢请 Star 哦♪(^∇^*)
|
5 | 5 |
|
6 | 6 | > 创建时间:2017-07-24
|
7 |
| -最后更新:2017-08-05 |
| 7 | +最后更新:2017-08-10 |
8 | 8 |
|
9 | 9 | ## 实现效果
|
10 |
| -## 知识点 |
11 |
| -## 过程指南 |
| 10 | +我们的目的是使网页模拟菜单的效果,在页面中添加新的菜品,而且在页面刷新之后也不清空。 |
12 | 11 |
|
13 |
| -默认情况下,在表单空间拥有焦点时按下 Enter 键或者点击提交按钮,会提交表单,提交时浏览器会在将请求发送给服务器之前触发 submit 事件,可以先添加事件监听后看看效果: |
14 |
| -```js |
15 |
| -function addItem(e) { |
16 |
| - console.log('hello'); |
17 |
| -} |
| 12 | +现在的初始页面中,点击提交按钮(Add Item)时页面默认触发 `submit` 事件,并重新加载页面,这导致重新加载之后的页面中,已丢失刚提交的内容。页面所用到的 CSS 文件已经完成了,我们需要做的是完成 JavaScript 部分的内容,以实现目标效果。 |
18 | 13 |
|
19 |
| -addItems.addEventListener('submit', addItem); |
20 |
| -``` |
21 |
| -结果就是 Console 中闪现 hello 后刷新整个页面,这是 submit 的默认行为,在当前的场景中不适用,先去除。 |
22 |
| -```js |
23 |
| -function addItem(e) { |
24 |
| - e.preventDefault(); |
25 |
| -} |
26 |
| -``` |
| 14 | +这一个挑战所用时间可能比之前的稍稍长一些,但理解了 localStorage 的机制,想明白菜单的实现之后,就会一目了然了,带上耐心我们开始吧~ |
27 | 15 |
|
| 16 | +## 知识点 |
| 17 | +- Event |
| 18 | + - [event.preventDefault](https://developer.mozilla.org/zh-CN/docs/Web/API/Event/preventDefault) |
| 19 | + - [eventTarget.addEventListener](https://developer.mozilla.org/zh-CN/docs/Web/API/EventTarget/addEventListener) |
| 20 | +- [localStorage](https://developer.mozilla.org/zh-CN/docs/Web/API/Storage/LocalStorage) |
| 21 | + - `localStorage.setItem()` |
| 22 | + - `localStorage.getItem()` |
| 23 | +- [JSON](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/JSON) |
| 24 | + - `JSON.stringify()` |
| 25 | + - `JSON.parse()` |
28 | 26 |
|
29 |
| -this 获取当前 form,是从 submit 事件获取到的。 |
| 27 | +## 过程指南 |
30 | 28 |
|
31 |
| -this.querySelector('[name=item]'); 获取其中的输入框 |
| 29 | +1. 默认情况下,在表单空间拥有焦点时按下 `Enter` 键或者点击提交按钮,会提交表单,提交时,浏览器会在发送请求给服务器之前触发 `submit` 事件,为了验证这个行为,我们可以添加事件监听后看看效果,此处先写一个处理函数: |
| 30 | + ```js |
| 31 | + function addItem(e) { |
| 32 | + console.log('hello'); |
| 33 | + } |
32 | 34 |
|
33 |
| -this.reset(); |
34 |
| -以清空 input 中正在输入的值 |
| 35 | + addItems.addEventListener('submit', addItem); |
| 36 | + ``` |
| 37 | + 点击按钮后发现 `submit` 事件触发后的结果是, Console 中闪现 hello 后刷新整个页面,这是 `submit` 的默认行为,在当前的场景中不适用,所以我们需要先去除此事件的默认行为。 |
| 38 | + ```js |
| 39 | + function addItem(e) { |
| 40 | + e.preventDefault(); |
| 41 | + } |
| 42 | + ``` |
35 | 43 |
|
36 |
| -使用 localStorage 的时候,直接传入 items 得到的是 [object Object],所以需要在把数据传进去之前就把内容转换成 String 类型的数据。 |
| 44 | +2. 下面我们开始改造 `addItem` 方法,以实现我们的功能。 |
| 45 | + 首先在事件监听中,`this` 可以获取当前 form 即我们为其添加事件监听的 `addItem` 元素,所以可以借此方便的获取输入框中的值。在 `addItem()` 方法中获取输入,并构造一个对象 `item` 来存储这个信息,: |
| 46 | + ```js |
| 47 | + /* function addItem(){} 中 */ |
| 48 | + const text = this.querySelector('[name=item]').value; |
| 49 | + const item = { |
| 50 | + text, // ES6中对 text: text, 的简写 |
| 51 | + done: false // 为后续的勾选做准备 |
| 52 | + } |
| 53 | + ``` |
| 54 | +3. 把对象放入此前声明好的数组 `items`,同时更新数据,包括页面中的 HTML 内容、LocalStorage。 |
| 55 | + ```js |
| 56 | + /* function addItem(){} 中 */ |
| 57 | + items.push(item); |
| 58 | + this.reset();// 以清空 input 中正在输入的值 |
| 59 | + populateList(items, itemsList); |
| 60 | + localStorage.setItem('items', JSON.stringify(items)); |
| 61 | + ``` |
| 62 | + - **HTML 内容更新** |
| 63 | + 声明一个 `populateList` 方法来更新页面的内容。接收需要更新的数组作为参数,根据数组里的内容构造一组 `<li>` 组成的列表,并且加上一些标识信息,以助于之后需要实现的选中功能。 |
| 64 | + ```js |
| 65 | + function populateList(plates = [], plateslist) { |
| 66 | + plateslist.innerHTML = plates.map((plate, i) => { |
| 67 | + return ` |
| 68 | + <li> |
| 69 | + <input type="checkbox" data-index=${i} id="item${i}" ${plate.done ? 'checked' : ''} > |
| 70 | + <label for="item${i}">${plate.text}</label> |
| 71 | + </li> |
| 72 | + `; |
| 73 | + }).join(''); |
| 74 | + } |
| 75 | + ``` |
| 76 | + - **LocalStorage 更新** |
| 77 | + 我们利用 LocalStorage 把信息存到本地,从而可以保证刷新后内容不变。但使用 `localStorage` 的时候,直接把 `items` 传入得到的值是 [object Object],所以需要在把数据传进去之前就把内容转换成 String 类型的数据,之后读取时也使用 `JSON.parse()` 来将数据转换成 JSON 格式。 |
0 commit comments