前端百题斩【024】——我从浏览器控制台看到了五种存储方式

本文涉及的产品
.cn 域名,1个 12个月
简介: 前端百题斩【024】——我从浏览器控制台看到了五种存储方式

打开浏览器的开发者工具中的Application部分,可以看到浏览器支持五种存储方式:localStorage、sessionStorage、IndexedDB、WebSQL、Cookie。其中W3C 官方在 2011 年 11 月声明已经不再维护 Web SQL Database 规范,所以本次主要讨论另外的三类四种存储方式:Cookie、Storage、IndexedDB。


640.png


24.1 Cookie


24.1.1 定义


Cookie是一个保存在浏览器中的简单的文本文件,该文件与特定的Web文档关联在一起,保存了该浏览器访问这个Web文档时的信息,当浏览器再次访问这个Web文档时这些信息可供该文档使用。(HTTP是无状态的协议,即HTTP协议本身不对请求和响应之间的通信状态进行保存,为了实现期望的保存状态功能,引入了cookie技术)


24.1.2 Cookie组成


在了解Cookie组成之前先了解一下Cookie的整个请求流程,这个流程分为两类:一类是没有Cookie信息状态下的请求,另一类是存有Cookie状态下的请求。


640.png


通过上面的流程图可以看出,Cookie是在服务端生成的,经过查询资料了解到其是在从服务端发送的响应报文内的一个叫做Set-Cookie的首部字段信息,响应报文中有该首部字段则通知客户端保存Cookie,则Cookie的组成则跟Set-Cookie可以设置哪些值相关,目前主要有以下几类:


  1. NAME=VALUE Cookie的名称和值,其中NAME是唯一标识cookie的名称,不区分大小写;VALUE是存储在Cookie里的字符串值,该值必须经过URL编码。
  2. Domain=域名 Cookie有效的域,发送到这个域的所有请求都会包含对应的Cookie。(若不指定则默认为创建Cookie的服务器的域名)
  3. Path=PATH 请求URL中包含这个路径才会把Cookie发送到服务器(若不指定则默认为文档所在的文件目录)
  4. Expires=DATE Cookie的有效期,默认情况下,浏览器会话结束后会删除所有cookie。
  5. Secure 设置后仅在HTTPS安全通信时才会发送Cookie
  6. HttpOnly 设置后只能在服务器上读取,不能再通过JavaScript读取Cookie


const express = require('express');
const app = express();
app.get('/', (req, res) => {
    res.cookie('myCookie', 'myCookie', {
        expires: new Date(Date.now() + 900000),
        secure: true,
        httpOnly: true
    });
    res.send('get请求已经被处理');
})
app.listen(8090, () => {
    console.log('8090端口已经启动!!!');
});


通过请求 http://127/.0.0.1:8090 来看看其结果:


640.png

640.png


24.1.3 Cookie特点


  1. 每个Cookie不超过4096字节;
  2. 每个域中Cookie个数有限制,就拿最新版来说:IE和Edge不超过50个;Firefox不超过150个;Opera不超过180个;Safari和Chrome没有限制;
  3. Cookie超过单个域的上限,浏览器会删除之前设置的Cookie;
  4. 创建的Cookie超过最大限制,该Cookie会被静默删除;
  5. 可设置失效时间,没有设置则会话结束会删除Cookie;
  6. 每个请求均会携带Cookie,若Cookie过多会带来性能问题;
  7. 受同源策略限制


24.1.4 Cookie的操作


Cookie存储到浏览器端之后仍然可以对其进行读、写、删除,由于js对Cookie操作的支持并不是很友好,所以需要进行一些简单的封装。


class CookieUtil {
    // 获取Cookie中的对应属性
    static get(name) {
        const cookies = document.cookie;
        const cookiesArr = cookies.split(';');
        for (let index = 0; index < cookiesArr.length; index++) {
            const presentCookieArr = cookiesArr[index].split('=');
            if (presentCookieArr[0] === name) {
                return presentCookieArr[1];
            }
        }
        return null;
    }
    // 设置对应的Cookie值
    static set(name, value, expires, path, domain, secure) {
        let cookieText = `${name}=${value}`;
        if (expires instanceof Date) {
            cookieText += `; expire=${expires.toGMTString()}`;
        }
        if (path) {
            cookieText += `; path=${path}`;
        }
        if (domain) {
            cookieText += `; domain=${domain}`;
        }
        if (secure) {
            cookieText += `; secure`;
        }
        document.cookie = cookieText;
    }
    // 删除对应的Cookie
    static deleteCookie(name) {
        CookieUtil.set(name, '', new Date(0));
    }
}


24.2 Web Storage



Web Storage的目的是解决通过客户端存储不需要频繁发送回服务器的数据时使用cookie的问题,其提供了cookie之外的存储会话数据的途径和跨会话持久化存储大量数据的机制,其主要有两个对象:localStorage和sessionStorage,localStorage是永久存储机制,sessionStorage是跨会话的存储机制。


24.2.1 sessionStorage


sessionStorage是跨会话的存储机制,具有以下特点:

  1. sessionStorage对象值存储会话数据,其生命周期会存储到浏览器关闭。(在该过程中刷新页面其数据不受影响)
  2. 浏览器在实现存储写入时使用同步阻塞方式,数据会被立即提交到存储。
  3. 独立打开同一个窗口同一个页面或一个Tab,sessionStorage也是不一样的。
  4. 存储空间大小限制为每个源不超过5M。


// 使用方法存储数据
sessionStorage.setItem('sessionName1', 'value1');
// 使用属性存储数据
sessionStorage.sessionName2 = 'value2';
// 使用方法取得数据
const sessionValue1 = sessionStorage.getItem('sessionName1');
console.log('sessionValue1的值为:', sessionValue1);
// 使用属性取得数据
const sessionValue2 = sessionStorage.sessionName2;
console.log('sessionValue2的值为:', sessionValue2);
// 循环遍历sessionStarage
for (let index = 0; index < sessionStorage.length; index++) {
    // 使用key()方法获得指定索引处的名称
    const key = sessionStorage.key(index);
    const value = sessionStorage.getItem(key);
    console.log('循环遍历结果:', key, value);
}
// 使用方法删除值
sessionStorage.removeItem('sessionName1');
// 使用delete删除值
delete sessionStorage.sessionName2;
// 使用clear()方法清空sessionStorage
sessionStorage.clear();


24.2.2 localStorage


localStorage是永久存储机制,具有以下特点:

  1. 生命周期是永久的,除非被清除,否则永久保存。
  2. 存储空间大小限制为每个源不超过5M。
  3. 受同源策略限制。
  4. 浏览器存储时采用同步存储方式。


// 使用方法存储数据
localStorage.setItem('localName1', 'value1');
// 使用属性存储数据
localStorage.localName2 = 'value2';
// 使用方法取得数据
const localValue1 = localStorage.getItem('localName1');
console.log('localValue1的值为:', localValue1);
// 使用属性取得数据
const localValue2 = localStorage.localName2;
console.log('localValue2的值为:', localValue2);
// 循环遍历localStarage
for (let index = 0; index < localStorage.length; index++) {
    // 使用key()方法获得指定索引处的名称
    const key = localStorage.key(index);
    const value = localStorage.getItem(key);
    console.log('循环遍历结果:', key, value);
}
// 使用方法删除值
localStorage.removeItem('localName1');
// 使用delete删除值
delete localStorage.localName2;
// 使用clear()方法清空localStorage
localStorage.clear();

24.3 IndexedDB



24.3.1 IndexedDB整个结构

640.png




对于整个IndexedDB为上述图中所示:


  1. 一个域名下可以包含多个数据库;
  2. 一个数据库中包含多个对象仓库,就类似与Mysql一个库中有多张表一样。
  3. 每个对象仓库中包含多条数据记录。


24.3.2 主要特点


IndexedDB是浏览器中存储结构化数据的一个方案,其设计几乎是完全异步的,主要有以下特点:


  1. 键值对存储 在对象仓库中,数据以“键值对”形式保存,每个数据记录都有独一无二的主键。


  1. 异步 IndexedDB操作时不会锁死浏览器,用户依然可以进行其它操作。


  1. 支持事务 一些列操作步骤之中只要有一步失败,整个事务就都取消,数据库回滚到事务发生之前的状态,不存在只改写一部分数据的情况。


  1. 受同源策略限制 只能访问自身域名下的数据库,不能跨域访问数据库。
  2. 存储空间大 每个源都有存储空间的限制,而且这个限制跟浏览器有关,例如Firefox限制每个源50MB,Chrome为5MB。


  1. 支持二进制存储 不仅可以存储字符串,还可以存储二进制数据(ArrayBuffer和Blob)


24.3.3 数据库操作


IndexedDB像很多其它数据库一样有很多操作,下面就通过实战的方式一起了解这些操作。


24.3.3.1 初始化数据库


第一步是初始化数据库,传入创建的数据库名和版本,获取对应的数据库操作实例。


class IndexedDBOperation {
  constructor(databaseName, version) {
      this.atabaseName = databaseName;
      this.version = version;
      this.request = null;
      this.db = null;
  }
  // 数据库初始化操作
  init() {
      this.request = window.indexedDB.open(this.databaseName, this.version);
      return new Promise((resolve, reject) => {
          this.request.onsuccess = event => {
              this.db = event.target.result;
              console.log('数据库打开成功');
              resolve('success');
          };
          this.request.onerror = event => {
              console.log('数据库打开报错');
              reject('error');
          };
          this.request.onupgradeneeded = event =>{
              this.db = event.target.result;
              console.log('数据库升级');
              resolve('upgradeneeded');
          };
      });
  }
}
24.3.3.2 对象仓库操作


数据是在对象仓库中存储的,创建好数据库后则需要创建所需的数据仓库


class IndexedDBOperation {
  // ……
  // 创建数据仓库
  createObjectStore(objectStoreName, options) {
      let objectStore = null;
      if (!this.db.objectStoreNames.contains(objectStoreName)) {
          objectStore = this.db.createObjectStore(objectStoreName, options);
      }
      return objectStore;
  }
}
24.3.3.3 数据操作


不管是关系型数据库还是非关系型数据库,CURD肯定是必不可少的,谁让我们是“CURD工程师”呢!!!


class IndexedDBOperation {
  // ……
  // 新增内容
  add(objectStore, content) {
      objectStore.add(content);
  }
  // 获取内容
  get(objectStore, id) {
      const request = objectStore.get(id);
      return new Promise((resolve, reject) => {
          request.onsuccess = resolve;
          request.onerror = reject;
      });
  }
  // 更新内容
  update(objectStore, content) {
      const request = objectStore.put(content);
      request.onsuccess = event => {
          console.log('更新成功');
      };
      request.onerror = event => {
          console.log('更新失败');
      };
  }
  // 删除内容
  remove(objectStore, deleteId) {
      const request = objectStore.delete(deleteId);
      request.onsuccess = event => {
          console.log('删除成功');
      };
      request.onerror = event => {
          console.log('删除失败');
      };
  }
}
24.3.3.4 遍历内容


提到IndexedDB数据库,不得不提其的游标操作。


class IndexedDBOperation {
  // ……
  // 打印全部数据
  printAllDataByCursor(objectStore) {
      const cursorRequest = objectStore.openCursor();
      cursorRequest.onsuccess = event => {
          const cursor = event.target.result;
          if (cursor) {
              console.log(`利用游标打印的内容,id为${cursor.key}, 值为${cursor.value}`);
              // 移动到下一条记录
              cursor.continue();
          }
      };
  }
}
24.3.3.5 调用代码


上面写了一个数据库的类,但是仍然不知道怎么调用呀,下面就用一个demo讲述其调用。


const indexedDBOperation = new IndexedDBOperation('dbName1', 1);
indexedDBOperation
.init()
.then(type => {
    const objectStoreName = 'testObjectStore';
    if (type === 'upgradeneeded') {
        indexedDBOperation.createObjectStore(objectStoreName, {
            keyPath: 'id'
        });
    }
    const transaction = indexedDBOperation.db.transaction([objectStoreName], 'readwrite');
    const objectStore = transaction.objectStore(objectStoreName);
    indexedDBOperation
    .get(objectStore, 1)
    .then(event => {
        if (event.target.result) {
            indexedDBOperation.update(objectStore, {
                id: 1,
                name: '执鸢者+纸鸢'
            });
            console.log('数据库中已经存在', event.target.result, ',则进行更新操作');
        }
        else {
            indexedDBOperation.add(objectStore, {
                id: 1,
                name: '执鸢者'
            });
            console.log('数据库中不存在,则进行添加');
        }
    })
    .catch(console.log);
    indexedDBOperation.printAllDataByCursor(objectStore);
    transaction.onsuccess = event => {
        console.log('事务操作成功');
    };
    transaction.onerror = event => {
        console.log('事务操作失败');
    };
    transaction.oncomplete = event => {
        console.log('整个事务成功完成');
    }
})
.catch(console.log);


相关文章
|
3月前
|
存储 人工智能 前端开发
前端大模型应用笔记(三):Vue3+Antdv+transformers+本地模型实现浏览器端侧增强搜索
本文介绍了一个纯前端实现的增强列表搜索应用,通过使用Transformer模型,实现了更智能的搜索功能,如使用“番茄”可以搜索到“西红柿”。项目基于Vue3和Ant Design Vue,使用了Xenova的bge-base-zh-v1.5模型。文章详细介绍了从环境搭建、数据准备到具体实现的全过程,并展示了实际效果和待改进点。
260 14
|
2月前
|
存储 监控 前端开发
如何实现前端框架数据驱动方式的数据加密存储?
实现前端框架数据驱动方式的数据加密存储需要综合考虑多个因素,包括加密算法的选择、密钥管理、传输安全、服务器端处理等。通过合理的设计和实施,能够有效提高数据的安全性,保护用户的隐私和敏感信息。但需要注意的是,前端加密存储不能完全替代后端的安全措施,后端的安全防护仍然是不可或缺的。
48 3
|
2月前
|
存储 前端开发 安全
如何确保前端框架数据驱动方式的数据加密存储的兼容性?
确保前端框架数据驱动方式的数据加密存储的兼容性需要综合考虑多个因素,通过充分的评估、测试、关注和更新,以及与其他技术的协调配合,来提高兼容性的可靠性,为用户提供稳定和安全的使用体验。
42 2
|
2月前
|
前端开发 JavaScript API
前端开发的秘密花园:这些技巧让你轻松应对各种浏览器兼容性问题!
【10月更文挑战第31天】前端开发是一个充满创意与挑战的领域,追求极致用户体验的同时,浏览器兼容性问题却时常阻碍我们前进。本文将介绍几种解决浏览器兼容性的最佳实践:使用CSS前缀、Autoprefixer工具、现代JavaScript特性与Babel转译、Polyfill与Feature Detection、响应式设计以及跨域问题处理。掌握这些技巧,助你轻松应对各种兼容性难题,创建更稳定、用户友好的网页应用。
50 3
|
2月前
|
机器学习/深度学习 自然语言处理 前端开发
前端神经网络入门:Brain.js - 详细介绍和对比不同的实现 - CNN、RNN、DNN、FFNN -无需准备环境打开浏览器即可测试运行-支持WebGPU加速
本文介绍了如何使用 JavaScript 神经网络库 **Brain.js** 实现不同类型的神经网络,包括前馈神经网络(FFNN)、深度神经网络(DNN)和循环神经网络(RNN)。通过简单的示例和代码,帮助前端开发者快速入门并理解神经网络的基本概念。文章还对比了各类神经网络的特点和适用场景,并简要介绍了卷积神经网络(CNN)的替代方案。
331 1
|
2月前
|
缓存 前端开发 JavaScript
"面试通关秘籍:深度解析浏览器面试必考问题,从重绘回流到事件委托,让你一举拿下前端 Offer!"
【10月更文挑战第23天】在前端开发面试中,浏览器相关知识是必考内容。本文总结了四个常见问题:浏览器渲染机制、重绘与回流、性能优化及事件委托。通过具体示例和对比分析,帮助求职者更好地理解和准备面试。掌握这些知识点,有助于提升面试表现和实际工作能力。
75 1
|
3月前
|
存储 弹性计算 算法
前端大模型应用笔记(四):如何在资源受限例如1核和1G内存的端侧或ECS上运行一个合适的向量存储库及如何优化
本文探讨了在资源受限的嵌入式设备(如1核处理器和1GB内存)上实现高效向量存储和检索的方法,旨在支持端侧大模型应用。文章分析了Annoy、HNSWLib、NMSLib、FLANN、VP-Trees和Lshbox等向量存储库的特点与适用场景,推荐Annoy作为多数情况下的首选方案,并提出了数据预处理、索引优化、查询优化等策略以提升性能。通过这些方法,即使在资源受限的环境中也能实现高效的向量检索。
|
3月前
|
存储 前端开发 JavaScript
🚀 10 个 GitHub 存储库,助你成为前端巨匠✨
本文介绍了10个极具价值的GitHub存储库,旨在帮助各级JavaScript开发人员提升技能。这些资源涵盖了从基本概念到高级算法、编码风格指南、面试准备等各个方面,包括经典书籍、实用工具和面试手册。无论您是刚入门的新手还是有经验的开发者,这些存储库都能为您提供丰富的学习资源,助您在JavaScript领域更进一步。探索这些资源,开启您的学习之旅吧!
81 0
🚀 10 个 GitHub 存储库,助你成为前端巨匠✨
|
3月前
|
机器学习/深度学习 自然语言处理 前端开发
前端大模型入门:Transformer.js 和 Xenova-引领浏览器端的机器学习变革
除了调用API接口使用Transformer技术,你是否想过在浏览器中运行大模型?Xenova团队推出的Transformer.js,基于JavaScript,让开发者能在浏览器中本地加载和执行预训练模型,无需依赖服务器。该库利用WebAssembly和WebGPU技术,大幅提升性能,尤其适合隐私保护、离线应用和低延迟交互场景。无论是NLP任务还是实时文本生成,Transformer.js都提供了强大支持,成为构建浏览器AI应用的核心工具。
739 1
|
3月前
|
NoSQL 前端开发 MongoDB
前端的全栈之路Meteor篇(三):运行在浏览器端的NoSQL数据库副本-MiniMongo介绍及其前后端数据实时同步示例
MiniMongo 是 Meteor 框架中的客户端数据库组件,模拟了 MongoDB 的核心功能,允许前端开发者使用类似 MongoDB 的 API 进行数据操作。通过 Meteor 的数据同步机制,MiniMongo 与服务器端的 MongoDB 实现实时数据同步,确保数据一致性,支持发布/订阅模型和响应式数据源,适用于实时聊天、项目管理和协作工具等应用场景。

热门文章

最新文章