Web Storage:数据储存机制

独泪了无痕 2024-10-21 13:33:02 阅读 74

image

前言

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

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

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

一、会话存储(sessionStorage)

1.1 什么是sessionStorage

image

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

1.2 如何使用sessionStorage

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

<code>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对应的是 <code>[‘object Object’] 呢?这是因为 sessionStorage 只能存储字符串类型,对于复杂对象可以使用ECMAScript对象的 stringify 处理。

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

image

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

image

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

image

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

二、本地存储(localStorage)

2.1 什么是localStorage

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

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

2.2 如何使用 localStorage

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

<code>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>code>

</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开始)获得键值

例如:

<code>/**

* 存入数据

*/

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项目的开发有所帮助。

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

在这里插入图片描述



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。