js之客户端存储(cookie、sessionStorage、localStorage、IndexedDB)

57 阅读7分钟

客户端存储主要用户存储用户的信息,无论时登录信息、个人偏好、还是其他数据,Web应用程序提供者都需要有办法把他们保存在客户端。

cookie

http cookie

http cookie通常也叫cookie,最初用于在客户端存储会话信息,要求服务器在相应HTTP请求时,通过发送Set-Cookie HTTP请求头包含会话信息。

HTTP/1.1 200
Server: nginx/1.20.1
Date: Thu, 25 May 2023 09:26:00 GMT
Content-Type: application/json;charset=utf-8
Set-Cookie:name=value

浏览器收到Set-Cookie之后,会将设置的cookie存储下来,并在之后的每个请求中都会通过HTTP头部cookie在将他们发回服务器。用于唯一标识发送请求的客户端。

cookie的构成

属性说明
名称唯一标识cookie的名称。
存储在cookie里的字符串值。
域 domaincookie的有效域,发送到这个域的所有请求都会包含对应的cookie。
路径 path请求URL中包含则个路径才会把cookie发送到服务器。
过期时间 expires标识合适删除cookie的时间戳
安全标志 secure设置之后,只在使用SSL安全连接的情况下才会把cookie发送到服务器。
HttpOnly设置之后,该属性只有在发送http请求时才能取到,通过document.cookie取不到。
HTTP/1.1 200
Server: nginx/1.20.1
Date: Thu, 25 May 2023 09:26:00 GMT
Content-Type: application/json;charset=utf-8
Set-Cookie:name=value;exprise=Thu May 25 2023 17:35:39 GMT;domain=www.xxx.com;path=/;secure

js中的cookie

在js中处理cookie较为复杂,js只提供了document.cookie接口用于获取cookie。

获取cookie:document.cookie返回页面中所有有效的cookie字符串(过期时间,路径等),以分号分隔。

console.log(document.cookie);//name=val;name1=val1

设置cookie:通过document.cookie设置新的cookie字符串。这个字符串在被解析之后会添加到原有cookie中,不会覆盖之前存在的任何cookie。

document.cookie = "name2=val2;path=/"
console.log(document.cookie);//name=val;name1=val1;name2=val2;

删除cookie:设置对应的cookie的过期时间为最早的时间戳。

document.cookie = "name2=val2;expires="+new Date(0);
console.log(document.cookie);//name=val;name1=val1;

sessionStorage

sessionStorage对象只会存储会话数据,着意味着只会存储到浏览器关闭。

存储在sessionStorage中的数据不受页面刷新影响,可以在浏览器崩溃并重启后恢复。

存储在sessionStorage对象中的数据只能由最初存储在数据的页面使用,在多页应用程序中的用处有限。

//1.写入数据
sessionStorage.setItem("name",'atuotuo');
//2.获取数据
let name = sessionStorage.getItem("name");
//3.删除数据
sessionStorage.removeItem("name");
//4.清空所有数据
sessionStorage.clear();
//5.获取sessionStorage中数据的个数
sessionStorage.length

localStorage

localStorage是客户端中持久存储数据的方法。要访问同一个localStorage对象,页面必须来自同一个域,在相同的端口上使用相同的协议。

存储在localStorage中的数据会保留到js删除,或者用户清除浏览器缓存

//1.写入数据
localStorage.setItem("name",'atuotuo');
//2.获取数据
let name = localStorage.getItem("name");
//3.删除数据
localStorage.removeItem("name");
//4.清空所有数据
localStorage.clear();
//5.获取sessionStorage中数据的个数
localStorage.length

存储时间

每当Storage对象发生变化时,都会在文档上触发storage事件,使用setItem或者removeItem删除值,以及每次调用clear都会触发这个事件。

window.addEventListener("storage",(e)=>{
    e.domain // 存储变化对应的域
    e.key // 改变的键
    e.newValue // 键被设置的新值,若被删除则为null
    e.oldValue // 键变化之前的值
 })

对于sessionStorage和localStorage上的任何更改都会触发storage事件,但storage事件不会区分着两者。

IndexedDB

IndexedDB是浏览器存储结构化数据的一个方案。绝大多数IndexDB操作要求添加onerror和onsuccess事件处理程序来确定输出。

数据库

IndexedDB类似于MySQL数据库,与传统数据库最大的区别在于,IndexedDB使用对象存储而不是表格保存数据,类似于NoSQL风格。

使用IndexedDB数据库的第一步就是调用IndexedDB.open()方法,并给他传入要打开的数据库名称,如果已存在则直接打开数据库。否则先创建数据库然后再打开。

open()方法会返回IDBRequest的实例,可以再实例上添加onsuccess和onerror事件处理程序。

const request = window.indexedDB.open('mydb', 1); // 第一个参数数据库名称,第二个参数版本号
request.onsuccess = e => {
  const db = e.target.result
}
request.onerror = e => {
  const db = e.target.result
}

对象存储objectStore

objectStore是indexedDB中非常核心的盖帘,他是数据的存储仓库,存放在相关的所有数据。

  1. 建立了数据库连接之后,下一步就是使用对象存储,相当于再数据库中创建表。
  2. 调用open()方法,会触发onupgradeneeded 事件,所以可以再这个事件中创建对象存储。
  3. 用 createObjectStore 方法来实现 objectStore 的创建,KeyPath用于指定存储对象的主键。
let user = {
    id:1
    username:'zs',
    age:18
}
const request = window.indexedDB.open('mydb', 1)
request.onupgradeneeded = (e) => {
  const db = e.target.result
  // 判断当前数据库中是否以及存在user存储对象
  if (!db.objectStoreNames.contains('user')) {
    db.createObjectStore('users', { keyPath: 'id' })
  }
}

事务

创建了对象存储之后,剩下的所有操作都是通过事务完成。

事务要通过调用数据库对象transaction方法创建。

  • 创建事务

    let transaction = db.transaction(['users'], 'readonly')
    // 参数一:传递0-n个存储对象
    // 参数二:传递访问方式,可选值:readonly | readwrite | versionchange
    
  • 通过事务引用,使用objectStore()方法并传入对象存储的名称以访问特定的对象存储,然后使用add(),put(),get()等方法操作,创建新的请求对象。

    let transaction = db.transaction(['users'], 'readonly')
    let objectStore = transaction.objectStore('users')
    let request = objectStore.get('username')
    

游标

使用事务可以通过一个已知键取得一条数据。如果想取得多条数据,则需要在事务中创建一个游标。

cursor 游标,就是 indexedDB 提供的遍历整个 objectStore 的能力接口。

let transaction = db.transaction(['users'], 'readonly')
let objectStore = transaction.objectStore('users')
let request = objectStore.openCursor() // 获取游标
let results = []
request.onsuccess = e => {
  let cursor = e.target.result
  if (cursor) {
    results.push(cursor.value)
    cursor.continue()
  }
  else {
    // 所有的object都在results里面
  }
}

索引

对某些数据集,可能需要为对象存储指定多个键。例如同时记录用户ID和用户名,那可能需要通过一种方式来获取用户数据。将用户ID作为主键,然后再用户名上创建索引。

要创建索引首先要获取对象存储的引用,然后再调用createIndex()

let request = window.indexedDB.open('user', 1)
request.onupgradeneeded = e => {
  let db = e.target.result
  let objectStore = db.createObjectStore('user', { keyPath: 'id' }) 
  objectStore.createIndex('username', 'username', { unique: true }) // unique必须指定,表示这个键是否再所有记录中唯一。
}

// 通过索引获取数据。
let transaction = db.transaction(['users'], 'readonly')
let objectStore = transaction.objectStore('users')
let index = objectStore.index("username");

// 在索引上创建游标,索引的用法和存储对象很像
let transaction = db.transaction(['users'], 'readonly')
let objectStore = transaction.objectStore('users')
let index = objectStore.index("username");
let request = index.openCursor();

操作数据

let transaction = db.transaction(['user'], 'readwrite')
let objectStore = transaction.objectStore('user')
// 获取数据
let request = objectStore.get(1) 
request.onsuccess = e => {
  let obj = e.target.result
}
// 添加数据
let request = objectStore.add({
  id: '100002',
  username: 'Zhang Fei',
  age:13
})
// 删除数据
let request = objectStore.delete('100001')
// 更新数据
let request = objectStore.put({
 id: '100002',
 name: 'Zhang Fei',
})

更多使用详情,请参考:developer.mozilla.org/zh-CN/docs/…

常见面试题

cookie、sessionStorage和localStorage的区别

特性CookielocalSotragesessionStorage
操作者服务器和jsjsjs
生命周期可以设置失效时间除非手动清除
否则永久保存
仅在当前会话下有效,
关闭页面或浏览器后被清除
数据大小4KB5MB5MB
与服务器通信每次都会携带在HTTP头中不与服务器通信不与服务器通信
易用性元素的cookie接口不友好,需要封装接口易用接口易用

什么是Cookie

cookie是浏览器的一直存储方式,通常在web上用于记录身份信息。

如何删除Cookie

设置cookie的过期时间

document.cookie = 'user=jeskson;expires='+new Date(0);

cookie的有效时间设置为0会怎么样

Cookie过期时间设置为0,表示跟随系统默认,其销毁与Session销毁时间相同,即都在浏览器关闭后的特定时间删除。如果我们写程序的时候不设置Cookie的有效时间,那么,Cookie的有效时间等效于会话时间。