客户端存储主要用户存储用户的信息,无论时登录信息、个人偏好、还是其他数据,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里的字符串值。 |
域 domain | cookie的有效域,发送到这个域的所有请求都会包含对应的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中非常核心的盖帘,他是数据的存储仓库,存放在相关的所有数据。
- 建立了数据库连接之后,下一步就是使用对象存储,相当于再数据库中创建表。
- 调用open()方法,会触发onupgradeneeded 事件,所以可以再这个事件中创建对象存储。
- 用 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的区别
特性 | Cookie | localSotrage | sessionStorage |
---|---|---|---|
操作者 | 服务器和js | js | js |
生命周期 | 可以设置失效时间 | 除非手动清除 否则永久保存 | 仅在当前会话下有效, 关闭页面或浏览器后被清除 |
数据大小 | 4KB | 5MB | 5MB |
与服务器通信 | 每次都会携带在HTTP头中 | 不与服务器通信 | 不与服务器通信 |
易用性 | 元素的cookie接口不友好,需要封装 | 接口易用 | 接口易用 |
什么是Cookie
cookie是浏览器的一直存储方式,通常在web上用于记录身份信息。
如何删除Cookie
设置cookie的过期时间
document.cookie = 'user=jeskson;expires='+new Date(0);
cookie的有效时间设置为0会怎么样
Cookie过期时间设置为0,表示跟随系统默认,其销毁与Session销毁时间相同,即都在浏览器关闭后的特定时间删除。如果我们写程序的时候不设置Cookie的有效时间,那么,Cookie的有效时间等效于会话时间。