资讯专栏INFORMATION COLUMN

Day15 - LocalStorage

用户84 / 2234人阅读

摘要:完整中文版指南及视频教程在从零到壹全栈部落。当页面重新刷新或者关闭之前,执行清除页面的缓存。慎用,尤其在生产环境中。

Day15 - LocalStorage

(Node+Vue+微信公众号开发)企业级产品全栈开发速成周末班首期班(10.28号正式开班,欢迎抢座)

作者:©黎跃春-追时间的人
简介:JavaScript30 是 Wes Bos 推出的一个 30 天挑战。项目免费提供了 30 个视频教程、30 个挑战的起始文档和 30 个挑战解决方案源代码。目的是帮助人们用纯 JavaScript 来写东西,不借助框架和库,也不使用编译器和引用。现在你看到的是这系列指南的第 14 篇。完整中文版指南及视频教程在 从零到壹全栈部落。

效果图

第十五天主要是练习LocalStorage(本地存储)以及时间委托的使用,使用场景是一个简单的todo list的应用,实现基本的添加item,切换完成状态,将所有todo项存储在localstorage中,保证刷新浏览器后数据不丢失。

主要思路

提前预定义好所有用到的变量;

// 添加item的按钮
const addItems = document.querySelector(".add-items"); 
// todolist列表
const itemsList = document.querySelector(".plates"); 
// 本地缓存的所有todoitem
const items = JSON.parse(localStorage.getItem("items")) || []; 

addItems按钮添加事件函数,添加一个新的todo item并存储到本地缓存;

监听checkbox的点击事件,切换是否完成的状态,并更新本地存储,保证刷新本页面是数据不会丢失;

分别设置两个监听器,监听addItemssubmit事件,和itemsList的点击事件;

添加item事件

添加item的主要代码如下

function addItem(e) {
  // 阻止默认事件的触发,防止在提交后页面自己刷新
  e.preventDefault(); 
  const text = this.querySelector("[name=item]").value;
  const item = {
    // ES6的简写形式 => text: text;
    text, 
    done: false
  };
  items.push(item);
  localStorage.setItem("items", JSON.stringify(items));
  populateList(items, itemsList);
  // 添加完数据后,重置输入框 
  this.reset();      
}
addItems.addEventListener("submit", addItem);

监听addItemssubmit事件,当用户点击enter或者点击右侧的submit按钮的时候触发;

text,是ES6的缩写形式,即代表text: text;
*localStorage的常用API:

localStorage.setItem(‘key’,value); -> 设置本地缓存,以key-value的形式

localStorage.getItem(‘key’); -> 根据参数key取得本地缓存中对应的值

localStorage.clear(); -> 清空本地的缓存

localStorage.removeItem(‘key’); -> 删除key所对应的那一条本地缓存

localStorage中只能存储字符串,所以我们经常会用到: JSON.stringify(object)将一个对象转换为字符串,再使用JSON.parse(objSting)将一个对象字符串转换为对象

this.reset();代表将表单重置,清空表单中的值,在我们进行了一次submit之后,如果不重置表单的话,表单中的值将不会消失,这将大大影响用户体验

切换完成状态事件
function toggleDone(e) {
  // if(!e.target.nodeName.match("INPUT")) return;
  
  // 跳过所有的input,只处理label
  if (!e.target.matches("input")) return; 
  const node = e.target;
  const index = node.dataset.index;
  items[index].done = !items[index].done;
  localStorage.setItem("items", JSON.stringify(items));
  populateList(items, itemsList);
}
itemsList.addEventListener("click", toggleDone);

此处使用到了事件委托,所谓事件委托,我是这么理解的:

假设我们队一个input列表进行了事件监听,但我们如法保证,此列表在接下来的状态下是否进行了更新,刷新等改变原来节点的操作,如果有这样的操作出现,那么我们之前的事件监听器就无法再起到监听的作用;

但我们可以对input列表的父元素进行事件监听,让它们的父元素处于监听状态,当我们所点击的元素是其子元素的话,就告诉它的子元素,执行相应的事件;

相当于委托父元素帮我们监听所有子元素,这样无论子元素列表进行怎么样的更新,改变,只要父元素节点不发生改变就可以持续起到监听的 作用。

通过e.target.matches("input")可以判断所点击的元素是不是input元素,e.target返回所点击的宿主元素。

通过获取到所点击的列表的序号,更改其done属性,更新后进行存储,就可以实现完成状态的事件。

列表显示函数
   // 设置默认值,防止传参数出错的时候crash
function populateList(populates = [], place {   
    place.innerHTML = populates.map((populate, index) => {
    //之所以用‘’空字符是因为如果用null的话,会出现在html中
    return `
      
  • `; // join()之后一定要加"",表示空字符,否则会加入逗号,造成错误 }).join(""); }

    将所有的列表项转化为li传入页面的html

    将此函数抽象出来,以方便以后实现同样类似的操作,将一个数组中的元素动态添加到页面的一个节点中

    清除缓存
        // 在关闭浏览器之后清除缓存
        window.onbeforeunload = function (e) {
          localStorage.removeItem("items");
          // let confirmationMessage = "o/";
          e.returnValue = confirmationMessage; // Gecko, Trident, Chrome 34+
          // return confirmationMessage; // 如果有返回值的话,就会弹出确认框。
        };

    有些时候,我们仅仅是为了练习localStorage的使用,并不想在浏览器中留下过多的缓存,那么这个方法就派上了用场。

    当页面重新刷新或者关闭之前,执行localStorage.removeItem("items’);清除页面的缓存。

    慎用,尤其在生产环境中。

    整体代码架构
    const addItems = document.querySelector(".add-items");
    const itemsList = document.querySelector(".plates");
    const items = JSON.parse(localStorage.getItem("items")) || [];
    
    function addItem(e) {
     e.preventDefault();
     const text = this.querySelector("[name=item]").value;
     const item = {
       text, // ES6的简写形式 => text = text;
       done: false
     };
     items.push(item);
     localStorage.setItem("items", JSON.stringify(items));
     populateList(items, itemsList);
     this.reset(); // 添加完数据后,重置输入框      
    }
    
    function populateList(populates = [], place) { // 设置默认值,防止传参数出错的时候crash
     place.innerHTML = populates.map((populate, index) => {
       return `
         
  • `; //之所以用‘’空字符是因为如果用null的话,会出现在html中 }).join(""); // join()之后一定要加"",表示空字符,否则会加入逗号,造成错误 } function toggleDone(e) { // if(!e.target.nodeName.match("INPUT")) return; if (!e.target.matches("input")) return; // 跳过所有的input,只处理label const node = e.target; const index = node.dataset.index; items[index].done = !items[index].done; localStorage.setItem("items", JSON.stringify(items)); populateList(items, itemsList); } addItems.addEventListener("submit", addItem); itemsList.addEventListener("click", toggleDone); populateList(items, itemsList);

    在页面加载的时候,先获取本地缓存的items,若存在就传给变量items,若第一次登录或者无item,初始化为空数组;

    在页面加载的时候先加载页面的所有todolist,执行一遍populateList(items, itemsList);函数即可。

    Github Source Code

    全栈部落 区块链部落

    文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

    转载请注明本文地址:https://www.ucloud.cn/yun/84640.html

    相关文章

    • JavaScript 30 - 一起做一次了不起的挑战

      摘要:加入我们,一起挑战吧扫码申请加入全栈部落 JavaScript 30 - 一起做一次了不起的挑战 (Node+Vue+微信公众号开发)企业级产品全栈开发速成周末班首期班(10.28号正式开班,欢迎抢座) 在Github上看到了wesbos的一个Javascript30天挑战的repo,旨在使用纯JS来进行练习,不允许使用任何其他的库和框架,该挑战共30天,我会在这里复现这30天遇到的挑...

      1treeS 评论0 收藏0
    • 多特蒙德主题本地个人任务清单小demo,你值得尝试!

      摘要:最后就是用各种的数据进行判断,渲染。否则任务的完成时间会出错,导致页面渲染错误。组件正在开发中,后期会分享,缺少弹窗提示,这里的操作动作很多,完全可以开发一个弹窗组件,方便用。 一,demo背景: 1,可以熟悉原生js 2,平时不知道自己学完js要做些什么东西的小伙伴 3,自己写的,可以当做自己的作品 4,为广大想练习练习原生js的贡献一个素材 二,实现功能: 1,新建/删除任务...

      Big_fat_cat 评论0 收藏0
    • 多特蒙德主题本地个人任务清单小demo,你值得尝试!

      摘要:最后就是用各种的数据进行判断,渲染。否则任务的完成时间会出错,导致页面渲染错误。组件正在开发中,后期会分享,缺少弹窗提示,这里的操作动作很多,完全可以开发一个弹窗组件,方便用。 一,demo背景: 1,可以熟悉原生js 2,平时不知道自己学完js要做些什么东西的小伙伴 3,自己写的,可以当做自己的作品 4,为广大想练习练习原生js的贡献一个素材 二,实现功能: 1,新建/删除任务...

      wuaiqiu 评论0 收藏0
    • 多特蒙德主题本地个人任务清单小demo,你值得尝试!

      摘要:最后就是用各种的数据进行判断,渲染。否则任务的完成时间会出错,导致页面渲染错误。组件正在开发中,后期会分享,缺少弹窗提示,这里的操作动作很多,完全可以开发一个弹窗组件,方便用。 一,demo背景: 1,可以熟悉原生js 2,平时不知道自己学完js要做些什么东西的小伙伴 3,自己写的,可以当做自己的作品 4,为广大想练习练习原生js的贡献一个素材 二,实现功能: 1,新建/删除任务...

      FullStackDeveloper 评论0 收藏0
    • JavaScript常用工具方法封装

      因为工作中经常用到这些方法,所有便把这些方法进行了总结。 JavaScript 1. type 类型判断 isString (o) { //是否字符串 return Object.prototype.toString.call(o).slice(8, -1) === String } isNumber (o) { //是否数字 return Object.prototype.to...

      孙淑建 评论0 收藏0

    发表评论

    0条评论

    用户84

    |高级讲师

    TA的文章

    阅读更多
    最新活动
    阅读需要支付1元查看
    <