因为使用了LocalStorage,添加的items再刷新后仍会保留。
这个教程挺好,很多我想了解的概念都出现了。
localStorage
特性 | Cookie | localStorage | sessionStorage |
---|---|---|---|
数据的生命期 | 一般由服务器生成,可设置失效时间。如果在浏览器端生成Cookie,默认是关闭浏览器后失效 | 除非被清除,否则永久保存 | 仅在当前会话下有效,关闭页面或浏览器后被清除 |
存放数据大小 | 4K左右 | 一般为5MB | |
与服务器端通信 | 每次都会携带在HTTP头中,如果使用cookie保存过多数据会带来性能问题 | 仅在客户端(即浏览器)中保存,不参与和服务器的通信 | |
易用性 | 需要程序员自己封装,源生的Cookie接口不友好 | 源生接口可以接受,亦可再次封装来对Object和Array有更好的支持 |
使用:
localStorage.setItem(key, value);
localStorage.getItem(key, value);
key和value只能是字符串,如果要存放object使用JSON.stringify和JSON.parse
要注意防止xss攻击
事件委托
事件委托,通俗地来讲,就是把一个元素响应事件(click、keydown……)的函数委托到另一个元素;
一般来讲,会把一个或者一组元素的事件委托到它的父层或者更外层元素上,真正绑定事件的是外层元素,当事件响应到需要绑定的元素上时,会通过事件冒泡机制从而触发它的外层元素的绑定事件上,然后在外层元素上去执行函数。
事件冒泡
前面提到 DOM 中事件委托的实现是利用事件冒泡的机制,那么事件冒泡是什么呢?
在 document.addEventListener 的时候我们可以设置事件模型:事件冒泡、事件捕获,一般来说都是用事件冒泡的模型;
addEventListener(event, function, useCapture)
如上图所示,事件模型是指分为三个阶段:
- 捕获阶段:在事件冒泡的模型中,捕获阶段不会响应任何事件;
- 目标阶段:目标阶段就是指事件响应到触发事件的最底层元素上;
- 冒泡阶段:冒泡阶段就是事件的触发响应会从最底层目标一层层地向外到最外层(根节点),事件代理即是利用事件冒泡的机制把里层所需要响应的事件绑定到外层;### 事件
委托的优点
1. 减少内存消耗
试想一下,若果我们有一个列表,列表之中有大量的列表项,我们需要在点击列表项的时候响应一个事件;
<ul id="list">
<li>item 1</li>
<li>item 2</li>
<li>item 3</li>
......
<li>item n</li>
</ul>
// ...... 代表中间还有未知数个 li
如果给每个列表项一一都绑定一个函数,那对于内存消耗是非常大的,效率上需要消耗很多性能;
因此,比较好的方法就是把这个点击事件绑定到他的父层,也就是 `ul` 上,然后在执行事件的时候再去匹配判断目标元素;
所以事件委托可以减少大量的内存消耗,节约效率。
2. 动态绑定事件
比如上述的例子中列表项就几个,我们给每个列表项都绑定了事件;
在很多时候,我们需要通过 AJAX 或者用户操作动态的增加或者去除列表项元素,那么在每一次改变的时候都需要重新给新增的元素绑定事件,给即将删去的元素解绑事件;
如果用了事件委托就没有这种麻烦了,因为事件是绑定在父层的,和目标元素的增减是没有关系的,执行到目标元素是在真正响应执行事件函数的过程中去匹配的;
所以使用事件在动态绑定事件的情况下是可以减少很多重复工作的。
本例中就是这种情况
本例
function toggleCheck(e) {
if (e.target.matches('input')) {
const index = e.target.dataset.index;
console.log(items[index])
items[index].done = !items[index].done;
populateList(items, itemsList);
localStorage.setItem('items', JSON.stringify(items));
}
}
itemsList.addEventListener('click', toggleCheck);
itemList是父元素,绑定监听click事件后,点一下会从内到外出现三个e.target。使用 e.target.matches(‘input’ )判断是checkbox被点击了后再进行操作。完成事件委托。
console.log(e.target);