根据id删除localstorage数据_原生js利用localstorage实现简易TODO list应用

62930d2c5e4d8403222fcf1de3c0a9d2.png

前言:小生不才,只懂得一些皮毛,我努力以最简单的语言将心中的想法表述出来,让更多人能够很轻松的弄明白。文章里面有不足之处望各位大牛指出,使得后面的文章能够朝着更好的方向发展。另外,大家记得点赞哟!

欢迎关注微信公众号:前端切图仔

参考文章:

天之蓝源:三分钟在GitHub上搭建个人博客​zhuanlan.zhihu.com
42b20b30730706ff552d610cea2473ec.png
天之蓝源:零基础Hexo+Github搭建静态个人博客​zhuanlan.zhihu.com
8c33c72413652a08344e4e62d942434c.png
天之蓝源:原生js实现点击按钮复制文本内容​zhuanlan.zhihu.com
bba245a24157d777f449e9626dd707ec.png
天之蓝源:九种跨域方式实现原理​zhuanlan.zhihu.com
2dfa777a7cae5cba30cb27c60613235e.png
天之蓝源:前端面试考点多?看这些文章就够了(转载)​zhuanlan.zhihu.com
a45b5f42a6a5aa392c32e865e0d27026.png
天之蓝源:干货!值得收藏的前端学习网站​zhuanlan.zhihu.com
6af354b5f7134ad2cbf4db42e3ff5b72.png
天之蓝源:原生JS实现一个日期选择器(DatePicker)组件​zhuanlan.zhihu.com
dad93cd80880846c232d8f64e79d7918.png
天之蓝源:原生js一步一步实现《别踩白块儿》小游戏​zhuanlan.zhihu.com
2531d44581cbc7bc517cf87cef0f96cf.png
天之蓝源:原生js利用localstorage实现简易TODO list应用​zhuanlan.zhihu.com
23c971b9fd3a7d60ee69e9cc3424ebf3.png
天之蓝源:原生js实现瀑布流效果​zhuanlan.zhihu.com
e7a8830e3dcb0c4356d1bafe63e481cc.png
天之蓝源:原生js实现图片懒加载(lazyLoad)​zhuanlan.zhihu.com
3aa80bd210a721531fb2326ab764066f.png
天之蓝源:原生js实现简单路由切换​zhuanlan.zhihu.com
d576f60ccf886946fc72c9e8d80caec9.png

实现的效果:

0249fb662549d5528c8696b87d2162df.png
利用本地存储实现todo 应用https://www.zhihu.com/video/1073999114060042240

一.todo list应用是什么?

可能很多小伙伴刚学完js或者其他知识的时候,不知道该怎么练习和巩固知识,然后这时候就可能会有人提出这样一个建议:写一个简单的todo list应用吧!

todo list应用其实很简单,就是一个待办事项列表应用,比如我们要做十件事,把这十件事添加到一个列表里面,然后办完一件事,我们就从列表中删除一件事,这就是一个最简单的todo list应用。接下来我们就要来实现这样一个最简单todo list应用,想要更完善的todo list应用可以自行百度学习更多知识。在本篇文章中我们利用localstorage将数据保存到本地,这样刷新浏览器数据就不会消失了。

二.什么是localstorage?

localStorage是HTML5新增的一个特性,主要是用来作为本地存储所使用的,我们都知道在之前,程序员们经常把数据存在cookie中,然后cookie的存储空间大约只有4kb,而新增的localStorage的存储容量大约有5M左右,这就解决了cookie存储容量不够的问题。但是,localStorage还是有它的优势和劣势的:

优势:

  • localStorage拓展了cookie的4K限制
  • localStorage会可以将第一次请求的数据直接存储到本地,这个相当于一个5M大小的针对于前端页面的数据库,相比于cookie可以节约带宽,但是这个却是只有在高版本的浏览器中才支持的

劣势:

  • 浏览器的大小不统一,并且在IE8以上的IE版本才支持localStorage这个属性
  • 目前所有的浏览器中都会把localStorage的值类型限定为string类型,这个在对我们日常比较常见的JSON对象类型需要一些转换
  • localStorage在浏览器的隐私模式下面是不可读取的
  • localStorage本质上是对字符串的读取,如果存储内容多的话会消耗内存空间,会导致页面变卡
  • localStorage不能被爬虫抓取到

另外:说起了localStorage,就不得不说一下sessionStorage,sessionStorage(会话存储)和localStorage(本地存储)的区别就是localStorage属于永久性存储,而sessionStorage属于当会话结束的时候,sessionStorage中的值就会被清空。

用法:

不管是 localStorage,还是 sessionStorage,可使用的API都相同,常用的有如下几个(以localStorage为例):

  • 保存数据:localStorage.setItem(key,value);
  • 读取数据:localStorage.getItem(key);
  • 删除单个数据:localStorage.removeItem(key);
  • 删除所有数据:localStorage.clear();
  • 得到某个索引的key:localStorage.key(index);

提示: 键/值对通常以字符串存储,你可以按自己的需要转换该格式。

三.什么是事件委托?

事件委托是前端面试中的一道经典题目,事件委托还有另外一个名字,事件代理。在红皮书《JavaScript高级程序设计》里面是这样解释事件委托的:事件委托就是利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。官方的语言始终是比较拗口,我们通俗一点来解释:比如我们有10个DOM节点,我们需要给每一个DOM都添加一个相同事件,那么我们就需要执行for循环给每个DOM元素添加事件,那要是有100个DOM元素呢,这样一个一个的赋予事件就是很繁琐的,而且这种繁琐的操作,直接导致了页面优化的问题。因此我们就想到了另外一个方法,那就是利用JS里面的冒泡原理,至于冒泡顾名思义就是一层一层的往上冒或者一层一层的往下冒,这事件也是一样,一层一层的往上冒,一层一层的往下冒,就这样,我们只需要给一个DOM节点赋予了事件,那么所有的DOM节点都有了这个事件。

这里就简单说了一下大致原理,具体内容可以百度:事件委托面试题等等,有很多不错的解释。

四.实现思路及步骤

(一)页面结构------>HTML代码

开局一条狗,后面全靠编。我们先把页面结构搭好,这才是第一步。

<body>
    <div class="wrapper">
        <h2>我是前端切图仔</h2>
        <p></p>
        <ul class="plates">
          <li>待添加事项</li>
        </ul>
        <form class="add-items">
          <input type="text" name="item" placeholder="Item Name" required>
          <input type="submit" value="添   加">
        </form>
        <div class="buttons">
            <button data-action="clear">删除所有</button>
            <button data-action="check">全部选中</button>
            <button data-action="uncheck">取消全选</button>
        </div>
    </div>
</body>

关于data-*属性,可以参照W3C,上面解释得挺清楚。

92f3793cee771081c4a9a9df60b5f19b.png
data-*属性设置介绍

(二)页面样式------>CSS代码

没有样式的HTML代码就是没有灵魂的,那么我们来给他添加一点灵魂吧:

html {
    min-height: 100vh;
    display: flex;
    justify-content: center;
    align-items: center;
}

.wrapper {
    padding: 20px;
    max-width: 350px;
    background: rgba(228, 215, 215, 0.95);
    box-shadow: 0 0 0 5px rgba(187, 157, 157, 0.5);
}
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:10px;
  outline:0;
  border:1px solid rgba(0,0,0,0.1);
}
.add-items input:nth-child(1){
  width: 61.3%;
}
.add-items input:nth-child(2) {
  width: 30%;
  color: rgb(85, 108, 128);
  font-weight: 700;
}
.buttons button {
  width: 100px;
  margin-top: 10px;
  height: 40px;
  color: rgb(85, 108, 128);
  font-weight: 700;
  border:1px solid rgba(0,0,0,0.1);
}

f61b546deecb7369c3484092002f775d.png
添加CSS样式后的页面

(三)页面逻辑------>JS代码

下面是最重要的js代码了,js代码负责我们的逻辑部分,是整个demo的核心,只要大家跟着注释解析代码很容易理解。

(function(){

    function newFun() {

        var addItems = document.querySelector('.add-items');//选中类为.add-items的元素
        var itemsList = document.querySelector('.plates');//todolist列表
        var buttons = document.querySelector('.buttons');
        var items = JSON.parse(localStorage.getItem('items')) || [];//获取本地缓存到的所有item,将一个对象字符串转换为对象

        //添加item方法
        function handleSubmit(e) {
            e.preventDefault();//阻止默认事件的触发,防止在提交后页面自己刷新
            var name = this.querySelector('[name=item]').value;//获取输入框中的值

            var item = {
                name: name,
                done: false//增加一个状态bool,后面会用到
            };
            items.push(item);
            localStorage.setItem('items', JSON.stringify(items));//将对象转化为字符串,因为本地存储只能以字符串的形式存储
            updateList( items, itemsList);//更新列表
            this.reset();
        }

        function updateList(plates = [], plateList) {
            plateList.innerHTML = plates.map( function(plate, i)  {

                return '<li><input type="checkbox" data-index="' + i + '" id="plate' + i + '" ' + (plate.done ? 'checked' : '') + ' /><label for="plate' + i + '">' + plate.name + '</label></li>';}).join('');
        }


        //事件委托
        // 此处使用到了事件委托:
        // 假设我们队一个input列表进行了事件监听,但我们如法保证,此列表在接下来的状态下是否进行了更新,刷新等改变原来节点的操作,如果有这样的操作出现,那么我们之前的事件监听器就无法再起到监听的作用;
        // 但我们可以对input列表的父元素进行事件监听,让它们的父元素处于监听状态,当我们所点击的元素是其子元素的话,就告诉它的子元素,执行相应的事件;
        // 相当于委托父元素帮我们监听所有子元素,这样无论子元素列表进行怎么样的更新,改变,只要父元素节点不发生改变就可以持续起到监听的 作用。
        // 通过e.target.matches('input')可以判断所点击的元素是不是input元素,e.target返回所点击的宿主元素。
        // 通过获取到所点击的列表的序号,更改其done属性,更新后进行存储,就可以实现完成状态的事件。
        function toggleChecked(e) {
            if (!e.target.matches('input')) return;
            var item = e.target.dataset.index;
            items[item].done = !items[item].done;
            localStorage.setItem('items', JSON.stringify(items));
            updateList( items, itemsList);
        }


        //添加button事件
        function doButtonPress(e) {
            var action = e.target.dataset.action;
            switch (action) {
                case "clear":
                    items = [];
                    break;
                case "check":
                    items.map( function(item) {
                        return item.done = true;
                    } );
                    break;
                case "uncheck":
                    items.map( function(item) {
                        return item.done = false ;
                    } );
                    break;
                default:
                    return;
            }
            localStorage.setItem('items', JSON.stringify(items));
            updateList( items, itemsList);
        }

        addItems.addEventListener('submit', handleSubmit);
        itemsList.addEventListener('click', toggleChecked);
        buttons.addEventListener('click', doButtonPress);

        updateList(items, itemsList);

    }

    document.addEventListener('DOMContentLoaded', newFun);
    //当初始的 HTML 文档被完全加载和解析完成之后,DOMContentLoaded 事件被触发,而无需等待样式表、图像和子框架的完成加载。另一个不同的事件 load 应该仅用于检测一个完全加载的页面。 在使用 DOMContentLoaded 更加合适的情况下使用 load 是一个令人难以置信的流行的错误,所以要谨慎。
    //注意:DOMContentLoaded 事件必须等待其所属script之前的样式表加载解析完成才会触发。

}());

(四)所有代码

五.总结

本次这个demo的核心就是localstorage(本地存储)的使用以及事件委托的理解,笔者也是在边写代码边理解,参照网上一些大牛的代码,遇到不懂的就上网百度,慢慢来实现。我们可以回顾一下我们是怎么做的:

  • 首先,一进入页面就添加事件DOMContentLoaded ,执行函数newFun
  • 然后就是获取dom元素和本地存储的元素
  • 然后有三个方法,分别是添加item元素,监听input列表方法,和点击button所执行的方法
  • 执行相应的函数

总的来说,虽然流程是比较清楚的,但是代码的细节还是需要仔细斟酌。

六.补充

在浏览器退出的时候可以清除一下缓存,因为这毕竟是我们的demo,没那么正式:

 window.onbeforeunload = function (e) {
      localStorage.removeItem('items');
      e.returnValue = confirmationMessage; // Gecko, Trident, Chrome 34+
};
window.onbeforeunload = function (event) {
      var message = 'Important: Please click on 'Save' button to leave this page.';
      if (typeof event == 'undefined') {
        event = window.event;
      }
      if (event) {
        event.returnValue = message;
      }
      return message;
};

七.源代码

更多源代码请移步GitHub

Hacker233/JavaScript​github.com
cf227316df9fa7a6268352d24611571f.png
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值