我们可以在控制台的Application下的storage中,看到浏览器的数据存储主要包括 localStorage、sessionStorage、IndexedDB、Cookies
浏览器存储区别概览
| cookie | sessionStorage | localstorage | indexedDB | ||
|---|---|---|---|---|---|
| 特点 | 存储类型 | 都是在客户端保存数据的,存储数据的类型:都是字符串 | **存储数据的类型:键值对储存。**不仅可以储存字符串,还可以储存二进制数据(ArrayBuffer 对象和 Blob 对象) | ||
| 生命周期 | 默认过期时间是session,临时存储,会话结束(关闭浏览器,关闭浏览器tab不会失效),cookie失效。 如果设置了有效时间,有效期到则失效。 | sessionStorage是在同源的窗口中始终存在的数据。仅在当前会话下有效,浏览器窗口没有关闭,刷新页面或者进入同源另一个页面,数据依然存在。 sessionStorage在关闭了浏览器窗口后就会被销毁。同时独立的打开同一个窗口同一个页面。 | localstorage永久的,关闭页面或浏览器之后数据也不会消失,除非手动清除,否则一直存在 | indexedDB永久的,关闭页面或浏览器之后数据也不会消失,除非手动清除,否则一直存在 IndexedDB 受同源限制,每一个数据库对应创建它的域名。网页只能访问自身域名下的数据库,而不能访问跨域的数据库。 | |
| 大小限制 | 4KB | 5M(单位:字符的长度/utf-16编码单元) | 无限容量 | ||
| 网络通信 | cookie的数据每次都会发给服务器端 | 不会与服务器端通信 | |||
| 同/异步 | 同步 | 异步 | |||
| 操作 | 保存 | document.cookie="name=value"; document.cookie="name=value;expires=过期时间"; | sessionStorage.setItem("key", "value"); | localStorage.setItem("key", "value"); | |
| 读取 | var x = document.cookie; | var lastname = sessionStorage.getItem("key"); | var lastname = localStorage.getItem("key"); | ||
| 删除 | document.cookie = "name=;expires=Thu, 01 Jan 1970 00:00:00 GMT"; | sessionStorage.removeItem("key"); | localStorage.removeItem("key"); | ||
| 删除所有 | 遍历删除 | sessionStorage.clear(); | localStorage.clear(); |
cookie、sessionStorage、localstorage的区别
相同点:
cookie,localStorage,sessionStorage都是在客户端保存数据的,存储数据的类型:都是字符串。
不同点: 1、生命周期:
cookie如果不设置有效期,就是临时存储(存储在内存中),是会话级别的,会话结束后,cookie也就失效了,如果设置了有效期,那么cookie存储在硬盘里,有效期到了,就自动消失了。localStorage的生命周期是永久的,那么关闭页面或浏览器之后localStorage中的数据也不会消失。localStorage除非主动删除数据,否则数据永远不会消失。sessionStorage仅在当前会话下有效。sessionStorage引入了一个“浏览器窗口”的概念,是在同源的窗口中始终存在的数据。只要这个浏览器窗口没有关闭,即使刷新页面或者进入同源另一个页面,数据依然存在。但是sessionStorage在关闭了浏览器窗口后就会被销毁。同时独立的打开同一个窗口同一个页面,sessionStorage也是不一样的。
2、网络通信:
cookie的数据每次都会发给服务器端,localstorage和sessionStorage不会与服务器端通信,webstorage更加节约网络流量。
3、大小限制:cookie大小限制在4KB,非常小;localstorage和sessionStorage在5M
4、安全性:WebStorage不会随着HTTP header发送到服务器端,所以安全性相对于cookie来说比较高一些,不会担心截获。
5、使用方便性上:WebStorage提供了一些方法,数据操作比cookie方便;
localstorage长度(已使用容量)计算?
计算已使用容量,我们只需要遍历localStorage身上的存储属性,并计算每一个的length,累加起来就是已使用的容量了
function sieOfLS() {
return Object.entries(localStorage).map(v => v.join("")).join("").length;
}
const useCache = sieOfLS()
console.log(`已用${useCache}KB`)
localstorage超出后会怎么样?
浏览器会怎么办:
- 不存储数据, 也不会覆盖现有数据。
- 引发 QUOTA_EXCEEDED_ERR 异常。报错如下图。
解决: localstorage存储不是5m 是每个域5m 超了申请其他的域/修改ng配置 postmessge通信往其他域上存取
indexedDB使用
打开/新建数据库,新建表、索引
新建数据库:window.indexedDB.open('库名') 新建表:IDBDatabase.createObjectStore()二个参数分别为表名、主键对象 新建索引:IDBObject.createIndex()的三个参数分别为索引名称、索引所在的属性、配置对象
// 打开数据库
const request = window.indexedDB.open('test');
// 新建数据库,更好的写法是先判断一下,这张表格是否存在,如果不存在再新建
request.onupgradeneeded = (event: any)=> {
console.log('数据库新建/升级触发成功');
db = event.target.result;
console.log('IDBDatabase:', db)
if (!db.objectStoreNames.contains('person')) {
// IDBDatabase.createObjectStore()二个参数分别为表名、主键对象
// IDBObject.createIndex()的三个参数分别为索引名称、索引所在的属性、配置对象
const objectStore = db.createObjectStore('person', { keyPath: 'id' });
objectStore.createIndex('name', 'name', { unique: false });
objectStore.createIndex('email', 'email', { unique: true });
console.log('IDBObject:', objectStore);
}
};
request.onsuccess = (event: any) => {
console.log('数据库打开成功');
db = event.target.result;
};
添加数据
const add = (index) => {
let request = db.transaction(['person'], 'readwrite')
.objectStore('person')
.add({ id: index, name: '张三' + index, age: 24 + index, email: `zhangsan${index}@example.com` });
request.onsuccess = () => {
console.log('数据写入成功');
};
request.onerror = () => {
console.log('数据写入失败');
};
}
读取数据
const getData = (key) => {
const request = db.transaction(['person']).objectStore('person').get(key);
request.onsuccess = () => {
if (request.result) {
console.log('Name: ', request.result);
} else {
console.log('未获得数据记录');
}
};
request.onerror = () => {
console.log('数据写入失败');
};
}
const readAll = () => {
const objectStore = db.transaction('person').objectStore('person');
objectStore.openCursor().onsuccess = (event: any) => {
const cursor = event.target.result;
if (cursor) {
console.log('Id: ' + cursor.key, cursor.value)
cursor.continue();
} else {
console.log('没有更多数据了!');
}
};
}
更新数据
const update = () => {
const request = db.transaction(['person'], 'readwrite')
.objectStore('person')
.put({ id: 1, name: '李四', age: 35, email: 'lisi@example.com' });
request.onsuccess = ()=> {
console.log('数据更新成功');
};
request.onerror = ()=> {
console.log('数据更新失败');
};
}
删除数据
删除一个或多个记录:delete(key/IDBKeyRange) 删除全部:clear()
const remove = () => {
// delete(key/IDBKeyRange)方法删除一个或者多个记录
// const keyRangeValue = IDBKeyRange.bound(1, 3);
// let request = db.transaction(['person'], 'readwrite')
// .objectStore('person')
// .delete(keyRangeValue);
let request = db.transaction(['person'], 'readwrite')
.objectStore('person')
.delete(1);
// clear()方法删除所有
// let request = db.transaction(['person'], 'readwrite')
// .objectStore('person')
// .clear();
request.onsuccess = ()=> {
console.log('数据删除成功');
};
request.onerror = ()=> {
console.log('数据删除失败');
};
}
查询数据
const search = () => {
const request = db.transaction(['person'], 'readonly')
.objectStore('person')
.index('name')
.get('张三3');
request.onsuccess = ()=>{
if(request.result){
console.log('查询结果', request.result)
}
};
request.onerror = ()=> {
console.log('数据查询失败');
};
}
vue3使用indexedDB完整demo
<template>
<div>
<el-button @click="add">添加</el-button>
<el-button @click="getData">读取一项数据</el-button>
<el-button @click="readAll">读取全部</el-button>
<el-button @click="update">更新1项数据</el-button>
<el-button @click="remove">删除</el-button>
<el-button @click="search">查询</el-button>
</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
let index = ref(0)
let db = {} as any
// 打开数据库
const request = window.indexedDB.open('test');
// 新建数据库,更好的写法是先判断一下,这张表格是否存在,如果不存在再新建
request.onupgradeneeded = (event: any)=> {
console.log('数据库新建/升级触发成功');
db = event.target.result;
console.log('IDBDatabase:', db)
if (!db.objectStoreNames.contains('person')) {
// IDBDatabase.createObjectStore()二个参数分别为表名、主键对象
// IDBObject.createIndex()的三个参数分别为索引名称、索引所在的属性、配置对象
const objectStore = db.createObjectStore('person', { keyPath: 'id' });
objectStore.createIndex('name', 'name', { unique: false });
objectStore.createIndex('email', 'email', { unique: true });
console.log('IDBObject:', objectStore);
}
};
request.onsuccess = (event: any) => {
console.log('数据库打开成功');
db = event.target.result;
};
const add = () => {
index.value++
let request = db.transaction(['person'], 'readwrite')
.objectStore('person')
.add({ id: index.value, name: '张三' + index.value, age: 24 + index.value, email: 'zhangsan' + index.value + '@example.com' });
request.onsuccess = () => {
console.log('数据写入成功');
};
request.onerror = () => {
console.log('数据写入失败');
};
}
const getData = () => {
const request = db.transaction(['person']).objectStore('person').get(1);
request.onsuccess = () => {
if (request.result) {
console.log('Name: ', request.result);
} else {
console.log('未获得数据记录');
}
};
request.onerror = () => {
console.log('数据写入失败');
};
}
const readAll = () => {
const objectStore = db.transaction('person').objectStore('person');
objectStore.openCursor().onsuccess = (event: any) => {
const cursor = event.target.result;
if (cursor) {
console.log('Id: ' + cursor.key, cursor.value)
cursor.continue();
} else {
console.log('没有更多数据了!');
}
};
}
const update = () => {
const request = db.transaction(['person'], 'readwrite')
.objectStore('person')
.put({ id: 1, name: '李四', age: 35, email: 'lisi@example.com' });
request.onsuccess = ()=> {
console.log('数据更新成功');
};
request.onerror = ()=> {
console.log('数据更新失败');
};
}
const remove = () => {
// delete(key/IDBKeyRange)方法删除一个或者一多个记录
// const keyRangeValue = IDBKeyRange.bound(1, 3);
// let request = db.transaction(['person'], 'readwrite')
// .objectStore('person')
// .delete(keyRangeValue);
let request = db.transaction(['person'], 'readwrite')
.objectStore('person')
.delete(1);
// clear()方法删除所有
// let request = db.transaction(['person'], 'readwrite')
// .objectStore('person')
// .clear();
request.onsuccess = ()=> {
console.log('数据删除成功');
};
request.onerror = ()=> {
console.log('数据删除失败');
};
}
const search = () => {
const request = db.transaction(['person'], 'readonly')
.objectStore('person')
.index('name')
.get('张三3');
request.onsuccess = ()=>{
if(request.result){
console.log('查询结果', request.result)
}
};
request.onerror = ()=> {
console.log('数据查询失败');
};
}
</script>