一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第20天,点击查看活动详情。
1、cookie
cookie
本身不是用来做服务器端存储的(计算机领域有很多这种“狗拿耗子”的例子,例如 CSS 中的 float),它是设计用来在服务器和客户端进行信息传递的,因此我们的每个 HTTP 请求都带着 cookie。但是 cookie 也具备浏览器端存储的能力(例如记住用户名和密码),因此就被开发者用上了。
使用起来也非常简单,document.cookie = ....
即可。
封装一个简单的setCookie
和getCookie
方法
function setCookie(c_name,value,expireseconds){
var exdate=new Date();
exdate.setTime(exdate.getTime()+expireseconds * 1000);
document.cookie=c_name+ "=" +escape(value)+
((expireseconds==null) ? "" : ";expires="+exdate.toGMTString())
}
function getCookie(c_name){
if (document.cookie.length>0){
c_start=document.cookie.indexOf(c_name + "=");
if (c_start!=-1){
c_start=c_start + c_name.length+1;
c_end=document.cookie.indexOf(";",c_start);
if (c_end==-1){
c_end=document.cookie.length;
}
return unescape(document.cookie.substring(c_start,c_end));
}
}
return "";
}
setCookie('name','zzyn',60); //cookie过期时间为60秒(1分钟)
getCookie('name')
但是 cookie 有它致命的缺点:
- 存储量太小,只有
4KB
- 所有 HTTP 请求都带着,会影响获取资源的效率
API
简单,需要封装才能用
对于 cookie 来说,还需要注意安全性。
属性 | 作用 |
---|---|
value | 如果用于保存用户登录态,应该将该值加密,不能使用明文的用户标识 |
http-only | 不能通过 JS 访问 Cookie ,减少 XSS 攻击 |
secure | 只能在协议为 HTTPS 的请求中携带 |
same-site | 规定浏览器不能在跨域请求中携带 Cookie ,减少 CSRF 攻击 |
2、localStorage
HTML5 标准就带来了sessionStorage
和localStorage
,先拿localStorage
来说,它是专门为了浏览器端缓存而设计的。其优点有:
- 存储量增大到 5MB
- 不会带到 HTTP 请求中
API
适用于数据存储localStorage.setItem(key, value)
localStorage.getItem(key)
使用
// set
localStorage.setItem(key, value)
// get
localStorage.getItem(key)
// clear
localStorage.removeItem(key);
【注】针对localStorage.setItem
,使用时尽量加入到try-catch
中,某些浏览器是禁用这个 API
的,要注意。
3、sessionStorage
sessionStorage
的区别就在于它是根据 session 过去时间而实现,而localStorage
会永久有效,应用场景不同。例如,一些需要及时失效的重要信息放在sessionStorage
中,一些不重要但是不经常设置的信息,放在localStorage
中。
使用
// set
sessionStorage.setItem(key, value)
// get
sessionStorage.getItem(key)
// clear
sessionStorage.removeItem(key);
4、indexDB
使用前端数据库
const req = window.indexDB.open('db_product', 1) // 打开/创建数据库
req.onsuccess = function (event) { // 监听数据库创建成功事件
let db = event.target.result // 数据库对象
console.log('数据库打开成功')
}
req.onerror = function (error) {
console.log('数据库打开报错')
}
req.onupgradeneeded = function (event) {
// 数据库创建或升级的时候会触发
db = event.target.result
let storeName = 'product' // 表名
if (!db.objectStoreNames.contains(storeName)) { // 判断表是否存在
let objectStore = db.createObjectStore(storeName, { keyPath: 'pro_id',autoIncrement: true })
}
}
总结
特性 | cookie | localStorage | sessionStorage | indexDB |
---|---|---|---|---|
数据生命周期 | 一般由服务器生成,可以设置过期时间 | 除非被清理,否则一直存在 | 页面关闭就清理 | 除非被清理,否则一直存在 |
数据存储大小 | 4K | 5M | 5M | 无限 |
与服务端通信 | 每次都会携带在 header 中,对于请求性能影响 | 不参与 | 不参与 | 不参与 |
从上表可以看到,
cookie
已经不建议用于存储。如果没有大量数据存储需求的话,可以使用localStorage
和sessionStorage
。对于不怎么改变的数据尽量使用localStorage
存储,否则可以用sessionStorage
存储
Service Worker
Service Worker
是运行在浏览器背后的独立线程,一般可以用来实现缓存功能。使用Service Worker
的话,传输协议必须为HTTPS
。因为Service Worker
中涉及到请求拦截,所以必须使用HTTPS
协议来保障安全Service Worker
实现缓存功能一般分为三个步骤:首先需要先注册Service Worker
,然后监听到install
事件以后就可以缓存需要的文件,那么在下次用户访问的时候就可以通过拦截请求的方式查询是否存在缓存,存在缓存的话就可以直接读取缓存文件,否则就去请求数据。以下是这个步骤的实现:
// index.js
if (navigator.serviceWorker) {
navigator.serviceWorker
.register('sw.js')
.then(function(registration) {
console.log('service worker 注册成功')
})
.catch(function(err) {
console.log('servcie worker 注册失败')
})
}
// sw.js
// 监听 `install` 事件,回调中缓存所需文件
self.addEventListener('install', e => {
e.waitUntil(
caches.open('my-cache').then(function(cache) {
return cache.addAll(['./index.html', './index.js'])
})
)
})
// 拦截所有请求事件
// 如果缓存中已经有请求的数据就直接用缓存,否则去请求数据
self.addEventListener('fetch', e => {
e.respondWith(
caches.match(e.request).then(function(response) {
if (response) {
return response
}
console.log('fetch source')
})
)
})
打开页面,可以在开发者工具中的 Application
看到 Service Worker
已经启动了,在 Cache
中也可以发现我们所需的文件已被缓存
当我们重新刷新页面可以发现我们缓存的数据是从 Service Worker
中读取的