Web Storage:数据储存机制

image

前言

  在HTML5之前,开发人员一般是通过使用Cookie在客户端保存一些简单的信息的。在HTML5发布后,提供了一种新的客户端本地保存数据的方法,那就是Web Storage,它也被分为:LocalStorage和SessionStorage,它允许通过JavaScript在Web浏览器中以键值对的形式保存数据。

  Web Storage 是一种在浏览器中存储数据的机制,允许在用户的浏览器中存储数据。在大多数情况下,可供我们使用就是LocalStorage和SessionStorage。但它们在数据的生命周期和存储限制上存在一些关键的区别。localStorage是一种持久化存储,即数据在关闭浏览器后也会保留。而 sessionStorage 是一种会话级的存储,即数据在关闭浏览器后会被清除。

Web Storage
localStorage
sessionStorage

  接下来,将会从安全性和用户体验两个方面对SessionStorage和LocalStorage进行评估。然后,将讨论如何根据实际业务要求挑选合适使用的对象。

一、会话存储(sessionStorage)

1.1 什么是sessionStorage

image

  sessionStorage 存储的数据在页面会话(session)期间有效,即只要浏览器窗口(或标签页)是打开的,刷新或者重新进入页面数据依然存在。一旦关闭窗口或标签页,存储的数据就会被删除,重新打开相同的窗口或标签页不会恢复数据。sessionStorage 存放数据大小为一般为5MB,而且它仅在客户端(即浏览器)中保存,不参与和服务器的通信。

1.2 如何使用sessionStorage

  sessionStorage 可以通过全局的 window 对象访问,因此可以直接使用。

sessionStorage = window.sessionStorage

  我们可以通过检查 window 对象是否包含 sessionStorage 属性,可以确定浏览器是否支持这个对象,如下所示:

function checkStorageSupport() {
    if (window.sessionStorage) {
        return true;
    } else {
        return false;
    }
}

  sessionStorage 的属性有Key和Value,保存了大量的数据。我们可以通过 setItem(key, value) 将数据存储到 sessionStorage 中,然后通过 getItem(key) 获取 sessionStorage 中的数据,如下图所示:

image

  这是不免会发现一个问题:存储是对象,为什么value对应的是 [‘object Object’] 呢?这是因为 sessionStorage 只能存储字符串类型,对于复杂对象可以使用ECMAScript对象的 stringify 处理。

sessionStorage.setItem('tg',JSON.stringify(person));

image

  同样在获取数据时,取出的是string类型,如下图所示。这也是sessionStorage只能存储字符串类型,对于复杂对象可以使用ECMAScript对象的 parse 处理。
image

const changeResult = JSON.parse(sessionStorage.getItem('tg'));

image

总之,通过转成字符串的形式存储,取出的时候转成对象,就能正常的存储和读取。

二、本地存储(localStorage)

2.1 什么是localStorage

  localStorage 提供了一种在浏览器中存储持久化数据的方式,即将数据保存到 localStorage 中,以便在刷新页面或重新打开应用后仍然能够访问数据。存储的数据没有时间限制,除非主动删除,否则数据会永久保存在浏览器中。即使关闭浏览器窗口或重新启动浏览器,数据依然存在。存放数据大小为一般为5MB,而且它仅在客户端(即浏览器)中保存,不参与和服务器的通信。

  LocalStorage 可跨浏览器窗口和选项卡间共享。就是说如果在多个选项卡和窗口中打开了一个应用程序,而一旦在其中一个选项卡或窗口中更新了 LocalStorage,则在所有其他选项卡和窗口中都会看到更新后的LocalStorage数据。常用于长期登录、判断是否已登录、适合长期保存在本地的数据。

2.2 如何使用 localStorage

  localStorage 可以通过浏览器 window 对象访问,因此可以直接使用,如下所示:

localStorage = window.localStorage;

  我们可以通过检查 window 对象是否包含 localStorage 属性,可以确定浏览器是否支持这个对象,如下所示:

function checkStorageSupport() {
    if(window.localStorage) {
        return true;
    } else {
        return false;
    }
}

  在 Vue 项目中,可以使用 window.localStorage 来进行 WebStorage的操作,通过 setItem(key, value) 将数据存储到 localStorage 中,通过 getItem(key) 获取 localStorage 中的数据。

// MyComponent.vue
<template>
	<div>{{ persistedData }}</div>
	<button @click="saveData">Save Data</button>
</template>

<script>
    export default {
        data() {	
            return {
                persistedData: ''
            }
        },
        methods: {
            saveData() {// 保存数据到localStorage
                localStorage.setItem('persistedData', 'Hello World');
            }
        },
        mounted() {// 从localStorage中读取数据
            this.persistedData = localStorage.getItem('persistedData');
        }
    }
</script>

  在这个例子中,我们在mounted钩子函数中读取localStorage中的数据并将其设置到组件的data中的persistedData属性中。同时,在saveData方法中将数据保存到localStorage中。

2.3 注意事项

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

三、其他

3.1 WebStorage 常用API

⚠️注意:注意:sessionStorage和localStorage的用法基本一致,引用类型的值要转换成JSON

方法说明
setItem(key: string, value: string)保存数据,以键值对的方式储存数据。
也就是说,每一项数据都有一个键名和对应的值。所有的数据都是以文本格式保存。
getItem(key: string)获取数据,将键值传入,即可获取到对应的value值。
removeItem(key: string)删除单个数据,根据键值移除对应的数据。
clear()删除所有保存的数据
key(index: number)根据位置(从0开始)获得键值

例如:

/**
 * 存入数据
 */
sessionStorage.setItem("key", "value");
localStorage.setItem("key", "value");

/**
 * 读取数据
 */
var valueSession = sessionStorage.getItem("key");
var valueLocal = localStorage.getItem("key");

/**
 * 用于清除某个键名对应的数据
 */
sessionStorage.removeItem('key');
localStorage.removeItem('key');

/**
 * 用于清除所有保存的数据
 */
sessionStorage.clear();
localStorage.clear();

/**
 * 利用length属性和key方法,可以遍历所有的键。
 */
for (var i = 0; i < localStorage.length; i++) {
    console.log(localStorage.key(i));
}

3.2 localStorage 工具类

  这里就不过多阐述了,直接看代码,如下所示:

const prefix = 'one_more_lsc_';

/**
 * 存储数据
 * @param key 键
 * @param val 值
 * @param expires 过期时间,单位为秒
 */
export const setItem = (key: string, value: any, expires: number) = >{
    key = prefix + key;
    value = JSON.stringify({
        'val': val,
        'expires': new Date().getTime() + expires * 1000
    });
    window.localStorage.setItem(key, value)
}

/**
 * 读取对应键的值数据
 * @param key 键
 * @returns  对应键的值
 */
export const getItem = (key: string) : any = >{
    key = prefix + key;
    let data = window.localStorage.getItem(key);
    if (!data) {
        return null;
    }
    data = JSON.parse(data);
    if (data.expires < new Date().getTime()) {
        localStorage.removeItem(key);
        return null;
    }
    return data.val;
}

/**
 * 删除指定数据
 */
export const removeItem = (key: string) = >{
    window.localStorage.removeItem(key)
}

/**
 * 删除所有数据
 */
export const removeAllItem = () = >{
    window.localStorage.clear()
}

  再上面代码中,我们实现了惰性删除,即某个键值过期后,该键值不会被马上删除,而是等到下次被使用的时候,才会被检查到过期,此时才能得到删除。惰性删除已经实现可过期的localStorage缓存,但是也有明显的缺点。如果一个key一直没有被用到,就不会被及时检查,即使过期了也一直存在localStorage。

  针对上述情况,对于不怎么常用 key 实现定时删除,即每隔一段时间执行一次删除操作,并通过限制删除操作执行的次数和频率,来减少删除操作对CPU的长期占用。另一方面定时删除也有效的减少了因惰性删除带来的对localStorage空间的浪费。每隔一秒执行一次定时删除,操作如下:1️⃣ 随机测试20个设置了过期时间的key;2️⃣ 删除所有发现的已过期的key;3️⃣ 若删除的key超过5个则重复步骤1,直到重复500次。

let prefix = 'one_more_lsc_'let list = [];

init();
// 每隔一秒执行一次定时删除
window.setInterval(self.check, 1000);

/**
 * 初始化list
 */
export const init = () = >{
    let keys = Object.keys(localStorage);
    let reg = new RegExp('^' + prefix);
    let temp = [];
    //遍历所有localStorage中的所有key
    for (var i = 0; i < keys.length; i++) {
        //找出可过期缓存的key
        if (reg.test(keys[i])) {
            temp.push(keys[i]);
        }
    }
    list = temp;
}

export const check = () = >{
    if (!list || list.length == 0) {
        return;
    }

    let checkCount = 0;
    while (checkCount < 500) {
        let expireCount = 0;
        // 随机测试20个设置了过期时间的key
        for (let i = 0; i < 20; i++) {
            if (list.length == 0) {
                break;
            }
            let index = Math.floor(Math.random() * list.length);
            let key = list[index];
            let val = localStorage.getItem(list[index]);
            // 从list中删除被惰性删除的key
            if (!val) {
                list.splice(index, 1);
                expireCount++;
                continue;
            }
            let = JSON.parse(val);
            //删除所有发现的已过期的key
            if (val.expires < new Date().getTime()) {
                list.splice(index, 1);
                localStorage.removeItem(key);
                expireCount++;
            }
        }
        //若删除的key不超过5个则跳出循环
        if (expireCount <= 5 || list.length == 0) {
            break;
        }
        checkCount++;
    }
}

3.3 storage事件

  当储存的数据发生变化时,会触发storage事件,我们可以指定这个事件的回调函数,回调函数接受一个event对象作为参数,如下所示:

window.addEventListener("storage",function(event) {
    // key:保存发生变化的键名
    console.log(e.key);
    // oldValue:更新前的值。如果该键为新增加,则这个属性为null。
    console.log(e.oldValue);
    // newValue:更新后的值。如果该键被删除,则这个属性为null。
    console.log(e.newValue);
    // url:原始触发storage事件的那个网页的网址。
    console.log(e.url);
});

image

  值得特别注意的是,该事件不在导致数据变化的当前页面触发。如果浏览器同时打开一个域名下面的多个页面,当其中的一个页面改变sessionStorage或localStorage的数据时,其他所有页面的storage事件会被触发,而原始页面并不触发storage事件。可以通过这种机制,实现多个窗口之间的通信。所有浏览器之中,只有IE浏览器除外,它会在所有页面触发storage事件。

四、小结

  在实际项目中,我们需要根据具体的需求来选择合适的数据缓存和本地存储方式。如果只是需要存储少量的数据,可以使用Cookies;如果需要存储大量的数据,并且需要在多个组件或页面之间共享使用,可以使用Vuex进行数据缓存;如果需要将数据持久化存储,可以使用localStorage。需要注意的是,在使用localStorage时要注意对数据进行序列化和反序列化,以保证数据能正确地被存储和读取。

  在Vue项目开发中,数据缓存和本地存储是非常重要的概念。合理使用数据缓存和本地存储可以提升应用程序的性能和用户体验。通过使用Vuex进行数据缓存和使用Cookies或Web Storage进行本地存储,我们可以更好地管理和使用数据。希望本文中的经验和实践对Vue项目的开发有所帮助。

把今天最好的表现当作明天最新的起点…….~

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/893469.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

配合工具,快速学习与体验electron增量更新

有任何问题&#xff0c;都可以私信博主&#xff0c;共同探讨学习。 正文开始 前言一、如何使用源码1.1 下载代码1.2 下载资源1.3 运行项目 二、如何使用工具2.1 打包新版本更新包2.2 创建nginx文件服务器2.3 在文件服务器保存软件更新包 三、如何测试更新3.1本地运行低版本3.2 …

centos 8.4学习小结

1.权限委派 2.vim快捷方式 2.1非正常关闭文本处理方式 2.2快捷方式 2.3TAB键补齐安装包 [ rootcloud Packages]# rpm -ivh bash-completion-2.7-5.el8.noarch.rpm 2.4#history 查询历史记录 [rootcloud ~]# vim /etc/profile HISTSIZE1000&#xff08;默认保存1000条历史记…

C++求日期差值题目

C日期差值题目&#xff08;牛客网&#xff09;题目超链接 仅个人思路不是最优解 仔细阅读地题目&#xff0c;要求输入连续的两串数字表示两个日期 所以我感觉日期类不太方便&#xff08;也许是我实力不允许&#xff09; cin使用起来就不太方便&#xff0c;我这里选择使用sca…

Spark的安装配置及集群搭建

Spark的本地安装配置&#xff1a; 我们用scala语言编写和操作spark&#xff0c;所以先要完成scala的环境配置 1、先完成Scala的环境搭建 下载Scala插件&#xff0c;创建一个Maven项目&#xff0c;导入Scala依赖和插件 scala依赖 <dependency><groupId>org.scal…

【途牛旅游网-注册/登录安全分析报告】

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 暴力破解密码&#xff0c;造成用户信息泄露短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造成亏损无底洞…

Java多线程--实现跑马小游戏

线程的实现方式 继承Thread类&#xff1a;void run()方法没有返回值&#xff0c;无法抛异常实现Runnable接口&#xff1a;void run()方法没有返回值&#xff0c;无法抛异常实现Callable接口&#xff1a;V call() throws Exception 返回结果&#xff0c;能够抛异常 实现Callab…

《Windows PE》6.4.2 远程注入DLL

实验四十七&#xff1a;远程注入DLL 写一个窗口程序&#xff0c;将一个dll通过远程注入的方法&#xff0c;注入到第三章的示例程序PEHeader.exe中&#xff0c;支持32位和64位PE。 ●dll.c /*------------------------------------------------------------------------FileNam…

【实战案例】JSR303统一校验与SpringBoot项目的整合

前后端分离项目中&#xff0c;当前前端请求后端接口的时候通常需要传输参数&#xff0c;对于参数的校验应该在哪一步进行校验&#xff1f;Controller中还是Service中&#xff1f;答案是都需要校验&#xff0c;只不过负责的板块不一样&#xff0c;Controller中通常校验请求参数的…

OpenCV高级图形用户界面(6)获取指定窗口中图像的矩形区域函数getWindowImageRect()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 提供窗口中图像的矩形区域。 该函数 getWindowImageRect 返回图像渲染区域的客户端屏幕坐标、宽度和高度。 函数原型 Rect cv::getWindowImage…

上海亚商投顾:沪指失守3200点 房地产板块集体下挫

上海亚商投顾前言&#xff1a;无惧大盘涨跌&#xff0c;解密龙虎榜资金&#xff0c;跟踪一线游资和机构资金动向&#xff0c;识别短期热点和强势个股。 一.市场情绪 市场全天冲高回落&#xff0c;沪指尾盘跌超1%&#xff0c;失守3200点关口。网络安全概念开盘大涨&#xff0c;…

Kaggle竞赛的流程 —— 手把手讲述如何完成一次kaggle比赛

Kaggle竞赛的工作流程&#xff1a; 1、加入竞赛&#xff1a; 看一下竞赛的描述&#xff0c;了解具体任务和数据集的情况之后&#xff0c;如果比较感兴趣这个比赛。点击Join Competition按钮&#xff0c;接受竞赛规则后&#xff0c;就可以访问比赛数据集啦。如下图所示&#xf…

08_实现 reactive

目录 编写 reactive 的函数签名处理对象的其他行为拦截 in 操作符拦截 for...in 循环delete 操作符 处理边界新旧值发生变化时才触发依赖的情况处理从原型上继承属性的情况处理一个对象已经是代理对象的情况处理一个原始对象已经被代理过一次之后的情况 浅响应与深响应代理数组…

Leetcode 跳跃游戏 二

核心任务是找出从数组的起点跳到终点所需的最小跳跃次数。 这段代码解决的是“跳跃游戏 II”&#xff08;Leetcode第45题&#xff09;&#xff0c;其核心任务是找出从数组的起点跳到终点所需的最小跳跃次数。 class Solution {public int jump(int[] nums) {//首先处理特殊情…

LabVIEW提高开发效率技巧----时序分析

一、什么是时序分析&#xff1f; 时序分析是优化LabVIEW程序性能的重要步骤。它通过分析程序各个部分的执行时间&#xff0c;帮助开发者找到程序运行中的瓶颈&#xff0c;并进行有针对性的优化。在LabVIEW中&#xff0c;Profile Performance and Memory工具是进行时序分析的关…

MySQL 免密登录的几种配置方式

文章目录 MySQL 免密登录的几种配置方式使用操作系统用户实现免密登录具体步骤&#xff1a;Step 1: 修改 MySQL 配置文件Step 2: 重启 MySQL 服务Step 3: 使用系统用户登录 MySQL优点&#xff1a;缺点&#xff1a; 使用 mysql_config_editor 配置免密文件具体步骤&#xff1a;S…

晶体与晶振的区别

概述 晶振是有源晶振的简称&#xff0c;又叫振荡器。英文名称是oscillator。 晶体则是无源晶振的简称&#xff0c;也叫谐振器。英文名称是crystal&#xff0c;电路上简称为XTAL。 无源晶振&#xff08;晶体&#xff09;&#xff1a;需要借助时钟电路才能产生振荡信号。 有源…

基于SpringBoot网上超市的设计与实现(论文+源码)_kaic

摘 要 网络技术和计算机技术发展至今&#xff0c;已经拥有了深厚的理论基础&#xff0c;并在现实中进行了充分运用&#xff0c;尤其是基于计算机运行的软件更是受到各界的关注。加上现在人们已经步入信息时代&#xff0c;所以对于信息的宣传和管理就很关键。因此超市商品销售信…

Oracle DECODE 丢失时间精度的原因与解决方案

在Oracle数据库中&#xff0c;DECODE 函数是一个非常实用的条件处理函数&#xff0c;通常用于替代简单的 CASE WHEN 语句。它根据给定的值列表进行匹配&#xff0c;如果匹配成功则返回相应的值。如果不匹配&#xff0c;返回一个默认值。 问题描述 SELECT DECODE(-21, -1, NU…

Python酷库之旅-第三方库Pandas(157)

目录 一、用法精讲 716、pandas.Timedelta.view方法 716-1、语法 716-2、参数 716-3、功能 716-4、返回值 716-5、说明 716-6、用法 716-6-1、数据准备 716-6-2、代码示例 716-6-3、结果输出 717、pandas.Timedelta.as_unit方法 717-1、语法 717-2、参数 717-3、…

MyBatis 框架搭建时依赖包引入异常

MyBatis 框架搭建时依赖包引入异常 问题&#xff1a;原因&#xff1a;解决办法&#xff1a; 问题&#xff1a; 在基于idea环境中学习搭建mybatis框架时&#xff0c;在maven工程的pom.xml文件中引入的 junit及mysql依赖包后&#xff0c;出现驼色阴影&#xff0c;提示信息如下图&…