1. 常用的存储方式
浏览器中的常用的存储方式有以下几种:
| 存储方式 | 解释 |
|---|---|
| cookie | 用于存储跨页面的简单数据,可以设置失效时间和作用域。 |
| session | 用于存储跨页面的简单数据,可以设置失效时间和作用域。 |
| sessionStorage | 与 localStorage 类似,但仅在当前会话期间有效,关闭标签页或浏览器时数据被清除。 |
| localStorage | 用于永久性存储关键数据,数据持久有效,如果用户不手动清除数据,就会一直存在 |
| IndexedDB | 浏览器本地数据库的标准 API,可存储大量、结构化的数据,允许异步事务处理。 |
| Web SQL Database | 一种轻量级的关系型数据库系统,使用 SQL 语言,可在浏览器中存储结构化、大量的数据。 |
| Cache API | 一种用于缓存网络请求的API,可以将请求和响应数据存储在浏览器中,以提高网站的性能。 |
| Service Worker | 一种独立于网页本身的 JavaScript 运行环境,可以拦截网络请求、缓存资源和提供离线支持。 |
除了上述的存储方式,还有File API、Sync API、Clipboard API、Device Storage API、Web Share API 等其它的存储技术。这些存储方式的使用根据具体的需求和浏览器支持情况而异。
2. 使用
2.1 cookie
class Cookie {
/** 读取 Cookie */
getItem(name) {
const regEx = new RegExp('(^|; )' + name + '=([^;]*)');
const result = document.cookie.match(regEx)
console.log('打印***result', result)
return result ? decodeURIComponent(result[2]) : null
}
/** 设置 Cookie */
setItem(name, value, days) {
let cookieStr = name + '=' + encodeURIComponent(value)
if (days) {
const expires = new Date()
expires.setTime(expires.getTime() + days)// *864e5 天数
cookieStr += ';expires=' + expires.toUTCString()
}
document.cookie = cookieStr
}
/** 删除 Cookie */
removeItem(name) {
const expires = new Date(0)
document.cookie = name + '=;expires=' + expires.toUTCString()
}
/** 删除所有 Cookie */
clear() {
const cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
let cookie = cookies[i];
let eqPos = cookie.indexOf('=');
let name = eqPos > -1 ? cookie.substr(0, eqPos) : cookie;
document.cookie = name + '=; expires=Thu, 01 Jan 1970 00:00:00 GMT';
}
}
}
const cookie = new Cookie()
可以使用js-cookie库进行操作
2.2 session
session是类似于cookie存储于服务器,有服务器生成可以返回给客户端进行存储,放入cookie中,必须是同源才能接收到
使用express进行搭建session生成存储
npm i express express-session cors -S
// index.js
const express = require('express');
const cors = require('cors')
const session = require('express-session');
const app = express();
app.use(cors())
// 将 public 目录设置为静态资源文件夹
app.use(express.static('public'));
// 设置 session 配置
app.use(
session({
secret: 'mySecretKey',
resave: false,
saveUninitialized: true,
name:'sid' // 存储在客户端cookie中的键
})
);
// 创建一个简单的路由,将访问次数存储在 session 中
app.get('/count', function (req, res) {
console.log('打印***req.session.views',req.session.views)
if (req.session.views) {
req.session.views++;
res.setHeader('Content-Type', 'text/html');
res.write('<p>访问次数: ' + req.session.views + '</p>');
res.end();
} else {
req.session.views = 1;
res.end('欢迎您首次光临!请刷新页面查看访问次数');
}
});
app.listen(3000, function() {
console.log('服务启动在 http://localhost:3000');
});
启动服务,打开http://localhost:3000/count 存储在客户端的sessionId
2.2 webStorage
2.3 Cache API
文档Experimental: 这是一个实验中的功能
caches.open('my-cache').then(function(cache) {
var request = 'http://localhost:3000/cache';
cache.match(request).then(function(response) {
if (response) {
return response;
}
return fetch(request).then(function(networkResponse) {
cache.put(request, networkResponse.clone());
return networkResponse;
});
}).then(function(response) {
console.log(response);
}).catch(function(error) {
console.error(error);
});
});
代码的执行逻辑如下:
-
调用caches.open('my-cache')方法打开一个名为"my-cache"的缓存。
-
调用cache.match(request)方法尝试从缓存中获取指定请求的资源。
-
如果在缓存中找到了资源,则直接返回缓存的响应。
-
如果在缓存中没有找到资源,继续执行下一步。
-
调用fetch(request)方法从网络获取请求的资源。
-
将请求响应存入缓存中,调用cache.put(request, networkResponse.clone())方法。
-
返回响应,即return networkResponse。
2.4 Service Worker
该代码段的作用是利用Service Worker中的缓存API,将请求过的资源存储在缓存中供以后使用,从而可以实现离线访问和性能优化等功能。
以下是一个使用Service Worker进行缓存和离线存储的示例,后端使用express进行搭建:
后端:
- 在项目目录中创建一个名为
index.js的文件
// npm init -y
// npm i express cors -S
const express = require('express');
const cors = require('cors')
const app = express();
app.use(cors())
// 将 public 目录设置为静态资源文件夹
app.use(express.static('public'));
app.get('/', function(req, res) {
// res.send('Hello World!');
res.sendFile(__dirname + '/index.html');
});
app.listen(3000, function() {
console.log('Example app listening on port 3000!');
});
这将设置一个简单的 Express 服务器,将静态文件提供在public目录中,并在根路由中处理请求。
- 创建名为
public的目录,然后在其中创建两个文件index.html和sw.js。
创建public文件夹
public
├─sw.js
├─styles
| └main.css
├─scripts
| └main.js
创建index.html文件
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="http://localhost:3000/styles/main.css" />
<script src="http://localhost:3000/scripts/main.js"></script>
<title>Service Worker Caching Example</title>
</head>
<body>
<h1>Service Worker Caching Example</h1>
<script>
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker
.register('/sw.js')
.then((registration) => {
console.log('Service Worker Registered:', registration);
})
.catch((err) => {
console.error('Service Worker Failed:', err);
});
});
}
</script>
</body>
</html>
这将注册 Service Worker 文件,即 sw.js。
- 在
sw.js中,进行基本的缓存操作:
sw.js
const CACHE_NAME = 'my-cache';
const urlsToCache = [
'/',
'/styles/main.css',
'/scripts/main.js'
];
self.addEventListener('install', (event) => {
event.waitUntil(
caches.open(CACHE_NAME)
.then((cache) => {
console.log('Opened cache');
return cache.addAll(urlsToCache);
})
);
});
self.addEventListener('fetch', (event) => {
event.respondWith(
caches.match(event.request)
.then((response) => {
if(response) {
return response;
}
return fetch(event.request).then(
(response) => {
if (!response || response.status !== 200 || response.type !== 'basic') {
return response;
}
const responseToCache = response.clone();
caches.open(CACHE_NAME)
.then((cache) => {
cache.put(event.request, responseToCache);
});
return response;
}
);
})
);
});
self.addEventListener('activate', (event) => {
const cacheWhitelist = [CACHE_NAME];
event.waitUntil(
caches.keys().then((cacheNames) => {
return Promise.all(
cacheNames.map((cacheName) => {
if (cacheWhitelist.indexOf(cacheName) === -1) {
return caches.delete(cacheName);
}
})
);
})
);
});
接下来,让我们为前端添加一些功能以探索缓存的使用。在public目录中创建以下文件:
styles/main.css
body {
font-family: Arial, sans-serif;
background-color: #f0f0f0;
}
.container {
max-width: 800px;
margin: 0 auto;
}
scripts/main.js
document.addEventListener('DOMContentLoaded', () => {
const updateCacheButton = document.createElement('button');
updateCacheButton.innerText = 'Update Cache';
const clearCacheButton = document.createElement('button');
clearCacheButton.innerText = 'Clear Cache';
const container = document.createElement('div');
container.classList.add('container');
container.appendChild(updateCacheButton);
container.appendChild(clearCacheButton);
document.body.appendChild(container);
updateCacheButton.addEventListener('click', () => {
fetch('/styles/main.css')
.then(response => response.text())
.then(css => console.log('CSS Fetched:', css));
});
clearCacheButton.addEventListener('click', () => {
caches.delete('my-cache')
.then(() => console.log('Cache Deleted'))
.catch(err => console.error('Cache Deletion Error:', err));
});
});
在index.html文件中的<body>标签中,添加以下内容以访问刚刚添加的样式和脚本文件。
<link rel="stylesheet" href="/styles/main.css" />
<script src="/scripts/main.js"></script>
node index.js启动服务,然后访问 http://localhost:3000 查看已更新的示例。 你会看到两个按钮 "Update Cache" 和 "Clear Cache"。 当您点击 "Update Cache" 时,服务工作器会将 "/styles/main.css" 文件添加到缓存中,或者将现有的缓存项更新为新请求的响应。查看开发者工具的控制台,您可以看到请求到的 CSS 文件的内容。
点击 "Clear Cache" 按钮时,将删除名为 "my-cache" 的缓存。通过浏览器开发者工具查看 Cache Storage,您可以观察到缓存的删除。
第一次:
离线设置:
3. 区别
cookie、session和localStorage都是用于在浏览器端存储数据的技术,但它们在存储数据的方式、范围和安全性方面有所不同。
- Cookie
Cookie 是在客户端存储数据的最早的技术之一,其主要作用是跟踪用户在网站上的活动。4kb
- 存储方式:Cookie 是通过 HTTP 请求从服务器发送到浏览器的一个小字符串,浏览器会将其存储在本地。在下一次请求时,该字符串会包含在请求头中,被服务器提取并分析。
- 范围:Cookie 的作用域是被设置它的那个域名,它只能被同一域名下加载的页面读取。
- 安全性:由于用户的个人信息通常会以明文方式存储在 Cookie 中,因此 Cookie 容易受到恶意攻击,特别是在不使用 HTTPS 安全协议的情况下。
- Session
与 Cookie 区别不大,Session 主要用于在服务器端存储用户信息。
- 存储方式:Session 是通过在服务器上创建一个唯一的会话 ID 和存储相应的用户信息来创建的。在会话期间,客户端的请求会被绑定到该会话,并传递此唯一 ID。如果客户端关闭浏览器,会话将被销毁。
- 范围:Session 的范围通常仅限于同一服务器上的网页。
- 安全性:即使用户的 Session ID 被盗,攻击者也无法从服务器端访问用户的数据。不过,如果 Web 应用程序存在漏洞,则攻击者可以访问未加密的 Session 数据。
- localStorage
localStorage 是 HTML5 新增加的一种本地存储方式,可以完全由客户端使用。localStorage 主要用于永久性存储关键数据。5-10MB
- 存储方式:localStorage 使用键值对的方式存储数据,数据仅限于字符串形式。存储到 localStorage 的数据永久生效,即使浏览器被关掉也不会清除。
- 范围:localStorage 数据的作用域在同一浏览器,即使在打开同一域名二级页面的情况下,localStorage 的数据也可以被读取和修改。
- 安全性:localStorage 是存在于浏览器缓存中的,因此容易受到恶意攻击。为了防止通过 XSS 攻击访问存储在 localStorage 中的敏感信息,可以使用加密和签名等安全措施。
总的来说,Cookie 用于存储跨页面的简单数据,Session 用于存储服务器端的用户信息,localStorage 用于永久性存储关键数据。应根据需求和应用程序的特点来选择合适的存储技术。
除了上述提到的 cookie、session 和 localStorage 外,浏览器还提供了以下几种存储方式:
- sessionStorage
sessionStorage 与 localStorage 非常相似,但数据仅在当前会话期间有效。如果用户关闭浏览器标签页或窗口,或者浏览器崩溃,则存储在 sessionStorage 中的数据将被清空。5-10MB
sessionStorage 使用方法与 localStorage 相同,只需将 "localStorage" 替换为 "sessionStorage" 即可。
- IndexedDB
IndexedDB 是浏览器本地数据库的标准 API,它可以在浏览器中存储大量、结构化的数据,比如 JSON 图形。IndexedDB 提供了一种异步事务的方式来处理数据的增删改查。
IndexedDB 的使用比较复杂,但在处理大量、复杂数据时非常有用。
- Web SQL Database
Web SQL Database 是一种轻量级的使用 SQL 的数据库系统,可以在浏览器中存储大量的结构化数据。Web SQL Database 具有类似于关系型数据库的特性,允许客户端查询数据并处理复杂的数据结构。
Web SQL Database 已被 Web 标准组织废弃和删除,但仍可在某些浏览器中使用。
- Service Worker
Service Worker 是一种比较新的浏览器存储技术,它是一种独立于网页本身的 JavaScript 运行环境,可以拦截网络请求、缓存资源和提供离线支持,使 Web 应用程序具有类似于本地应用程序的功能。
Service Worker 可以在后台更新缓存数据,并在用户重新访问页面时使用这些数据,从而提高应用程序的响应速度和性能。此外,Service Worker 还可以运行离线脚本、推送通知和执行一些高级任务,例如前台进程处理和数据同步等。
总的来说,浏览器还有很多存储技术可以选择,每种技术都有各自的优缺点和适用场景。根据应用程序的需求和平台支持情况,选择适合的存储技术是非常重要的。