浏览器数据存储区别与indexedDB使用

287 阅读4分钟

image.png

我们可以在控制台的Application下的storage中,看到浏览器的数据存储主要包括 localStorage、sessionStorage、IndexedDB、Cookies

浏览器存储区别概览

cookiesessionStoragelocalstorageindexedDB
特点存储类型都是在客户端保存数据的,存储数据的类型:都是字符串**存储数据的类型:键值对储存。**不仅可以储存字符串,还可以储存二进制数据(ArrayBuffer 对象和 Blob 对象)
生命周期默认过期时间是session,临时存储,会话结束(关闭浏览器,关闭浏览器tab不会失效),cookie失效。

如果设置了有效时间,有效期到则失效。
sessionStorage是在同源的窗口中始终存在的数据。仅在当前会话下有效,浏览器窗口没有关闭,刷新页面或者进入同源另一个页面,数据依然存在。

sessionStorage在关闭了浏览器窗口后就会被销毁。同时独立的打开同一个窗口同一个页面。
localstorage永久的,关闭页面或浏览器之后数据也不会消失,除非手动清除,否则一直存在indexedDB永久的,关闭页面或浏览器之后数据也不会消失,除非手动清除,否则一直存在

IndexedDB 受同源限制,每一个数据库对应创建它的域名。网页只能访问自身域名下的数据库,而不能访问跨域的数据库。
大小限制4KB5M(单位:字符的长度/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的数据每次都会发给服务器端,
  • localstoragesessionStorage不会与服务器端通信,webstorage更加节约网络流量。

3、大小限制cookie大小限制在4KB,非常小;localstoragesessionStorage在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 异常。报错如下图。

image.png

解决: 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

image.png

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