Web Storage:数据储存机制

前言

在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

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

1.2 如何使用sessionStorage

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

javascript 复制代码
sessionStorage = window.sessionStorage

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

javascript 复制代码
function checkStorageSupport() {
    if (window.sessionStorage) {
        return true;
    } else {
        return false;
    }
}

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

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

javascript 复制代码
sessionStorage.setItem('tg',JSON.stringify(person));

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

javascript 复制代码
const changeResult = JSON.parse(sessionStorage.getItem('tg'));

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

二、本地存储(localStorage)

2.1 什么是localStorage

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

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

2.2 如何使用 localStorage

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

javascript 复制代码
localStorage = window.localStorage;

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

javascript 复制代码
function checkStorageSupport() {
    if(window.localStorage) {
        return true;
    } else {
        return false;
    }
}

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

html 复制代码
// 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开始)获得键值

例如:

javascript 复制代码
/**
 * 存入数据
 */
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 工具类

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

javascript 复制代码
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次。

javascript 复制代码
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对象作为参数,如下所示:

javascript 复制代码
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);
});

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

四、小结

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

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

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

相关推荐
崔庆才丨静觅7 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60618 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了8 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅8 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅8 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅9 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment9 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅9 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊9 小时前
jwt介绍
前端
爱敲代码的小鱼9 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax