存储机制
存储方式对比
浏览器提供多种存储方式,各有优缺点和适用场景。
| 存储方式 | 容量 | 过期时间 | 作用域 | 用途 |
|---|---|---|---|---|
| Cookie | 4KB | 可设置 | 同源 | 会话管理、个性化 |
| LocalStorage | 5-10MB | 永久 | 同源 | 长期存储 |
| SessionStorage | 5-10MB | 会话结束 | 同源标签页 | 临时存储 |
| IndexedDB | 大容量 | 永久 | 同源 | 结构化数据 |
| WebSQL | 大容量 | 永久 | 同源 | 结构化数据(已废弃) |
Cookie
基本用法
javascript
// 设置Cookie
document.cookie = 'name=value';
// 设置过期时间
document.cookie = 'name=value; expires=Wed, 21 Oct 2024 07:28:00 GMT';
// 设置路径
document.cookie = 'name=value; path=/';
// 设置域名
document.cookie = 'name=value; domain=example.com';
// 设置安全标志
document.cookie = 'name=value; secure';
// 设置HttpOnly标志
document.cookie = 'name=value; HttpOnly';
// 设置SameSite
document.cookie = 'name=value; SameSite=Strict';读取Cookie
javascript
// 读取所有Cookie
console.log(document.cookie);
// 解析Cookie
function getCookie(name) {
const cookies = document.cookie.split(';');
for (let cookie of cookies) {
const [key, value] = cookie.trim().split('=');
if (key === name) {
return value;
}
}
return null;
}
const value = getCookie('name');
console.log(value);删除Cookie
javascript
// 删除Cookie
document.cookie = 'name=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/';Cookie属性
javascript
// 完整示例
document.cookie = 'name=value; expires=Wed, 21 Oct 2024 07:28:00 GMT; path=/; domain=example.com; secure; HttpOnly; SameSite=Strict';LocalStorage
基本用法
javascript
// 设置数据
localStorage.setItem('key', 'value');
// 读取数据
const value = localStorage.getItem('key');
console.log(value);
// 删除数据
localStorage.removeItem('key');
// 清空所有数据
localStorage.clear();
// 获取所有键
for (let i = 0; i < localStorage.length; i++) {
const key = localStorage.key(i);
const value = localStorage.getItem(key);
console.log(key, value);
}存储对象
javascript
// 存储对象
const user = {
name: 'John',
age: 30,
email: 'john@example.com'
};
localStorage.setItem('user', JSON.stringify(user));
// 读取对象
const userJson = localStorage.getItem('user');
const userObj = JSON.parse(userJson);
console.log(userObj);监听变化
javascript
// 监听LocalStorage变化
window.addEventListener('storage', (event) => {
console.log('Key:', event.key);
console.log('Old Value:', event.oldValue);
console.log('New Value:', event.newValue);
console.log('URL:', event.url);
});SessionStorage
基本用法
javascript
// 设置数据
sessionStorage.setItem('key', 'value');
// 读取数据
const value = sessionStorage.getItem('key');
console.log(value);
// 删除数据
sessionStorage.removeItem('key');
// 清空所有数据
sessionStorage.clear();与LocalStorage的区别
javascript
// LocalStorage: 永久存储,同源所有标签页共享
localStorage.setItem('key', 'value');
// SessionStorage: 会话结束清除,只对当前标签页有效
sessionStorage.setItem('key', 'value');IndexedDB
基本用法
javascript
// 打开数据库
const request = indexedDB.open('myDatabase', 1);
request.onerror = function(event) {
console.error('Database error:', event.target.error);
};
request.onsuccess = function(event) {
const db = event.target.result;
console.log('Database opened successfully');
};
request.onupgradeneeded = function(event) {
const db = event.target.result;
// 创建对象存储
const objectStore = db.createObjectStore('users', { keyPath: 'id', autoIncrement: true });
// 创建索引
objectStore.createIndex('name', 'name', { unique: false });
objectStore.createIndex('email', 'email', { unique: true });
};添加数据
javascript
const request = indexedDB.open('myDatabase', 1);
request.onsuccess = function(event) {
const db = event.target.result;
const transaction = db.transaction(['users'], 'readwrite');
const objectStore = transaction.objectStore('users');
const user = {
name: 'John',
age: 30,
email: 'john@example.com'
};
const addRequest = objectStore.add(user);
addRequest.onsuccess = function(event) {
console.log('Data added successfully');
};
addRequest.onerror = function(event) {
console.error('Add error:', event.target.error);
};
};读取数据
javascript
const request = indexedDB.open('myDatabase', 1);
request.onsuccess = function(event) {
const db = event.target.result;
const transaction = db.transaction(['users'], 'readonly');
const objectStore = transaction.objectStore('users');
const getRequest = objectStore.get(1);
getRequest.onsuccess = function(event) {
const user = event.target.result;
console.log(user);
};
};更新数据
javascript
const request = indexedDB.open('myDatabase', 1);
request.onsuccess = function(event) {
const db = event.target.result;
const transaction = db.transaction(['users'], 'readwrite');
const objectStore = transaction.objectStore('users');
const user = {
id: 1,
name: 'John',
age: 31,
email: 'john@example.com'
};
const putRequest = objectStore.put(user);
putRequest.onsuccess = function(event) {
console.log('Data updated successfully');
};
};删除数据
javascript
const request = indexedDB.open('myDatabase', 1);
request.onsuccess = function(event) {
const db = event.target.result;
const transaction = db.transaction(['users'], 'readwrite');
const objectStore = transaction.objectStore('users');
const deleteRequest = objectStore.delete(1);
deleteRequest.onsuccess = function(event) {
console.log('Data deleted successfully');
};
};查询数据
javascript
const request = indexedDB.open('myDatabase', 1);
request.onsuccess = function(event) {
const db = event.target.result;
const transaction = db.transaction(['users'], 'readonly');
const objectStore = transaction.objectStore('users');
const index = objectStore.index('name');
const getRequest = index.get('John');
getRequest.onsuccess = function(event) {
const user = event.target.result;
console.log(user);
};
};存储封装
LocalStorage封装
javascript
class Storage {
constructor(prefix = 'app_') {
this.prefix = prefix;
}
set(key, value) {
const data = JSON.stringify(value);
localStorage.setItem(this.prefix + key, data);
}
get(key) {
const data = localStorage.getItem(this.prefix + key);
return data ? JSON.parse(data) : null;
}
remove(key) {
localStorage.removeItem(this.prefix + key);
}
clear() {
const keys = Object.keys(localStorage);
keys.forEach(key => {
if (key.startsWith(this.prefix)) {
localStorage.removeItem(key);
}
});
}
}
const storage = new Storage();
storage.set('user', { name: 'John', age: 30 });
const user = storage.get('user');
console.log(user);IndexedDB封装
javascript
class IndexedDBHelper {
constructor(dbName, version) {
this.dbName = dbName;
this.version = version;
this.db = null;
}
async open() {
return new Promise((resolve, reject) => {
const request = indexedDB.open(this.dbName, this.version);
request.onsuccess = () => {
this.db = request.result;
resolve(this.db);
};
request.onerror = () => {
reject(request.error);
};
request.onupgradeneeded = (event) => {
const db = event.target.result;
this.onUpgrade(db, event.oldVersion, event.newVersion);
};
});
}
onUpgrade(db, oldVersion, newVersion) {
// 子类实现
}
async add(storeName, data) {
const transaction = this.db.transaction([storeName], 'readwrite');
const objectStore = transaction.objectStore(storeName);
return new Promise((resolve, reject) => {
const request = objectStore.add(data);
request.onsuccess = () => resolve(request.result);
request.onerror = () => reject(request.error);
});
}
async get(storeName, key) {
const transaction = this.db.transaction([storeName], 'readonly');
const objectStore = transaction.objectStore(storeName);
return new Promise((resolve, reject) => {
const request = objectStore.get(key);
request.onsuccess = () => resolve(request.result);
request.onerror = () => reject(request.error);
});
}
async update(storeName, data) {
const transaction = this.db.transaction([storeName], 'readwrite');
const objectStore = transaction.objectStore(storeName);
return new Promise((resolve, reject) => {
const request = objectStore.put(data);
request.onsuccess = () => resolve(request.result);
request.onerror = () => reject(request.error);
});
}
async delete(storeName, key) {
const transaction = this.db.transaction([storeName], 'readwrite');
const objectStore = transaction.objectStore(storeName);
return new Promise((resolve, reject) => {
const request = objectStore.delete(key);
request.onsuccess = () => resolve();
request.onerror = () => reject(request.error);
});
}
}
class UserDB extends IndexedDBHelper {
constructor() {
super('UserDB', 1);
}
onUpgrade(db, oldVersion, newVersion) {
if (oldVersion < 1) {
const objectStore = db.createObjectStore('users', { keyPath: 'id', autoIncrement: true });
objectStore.createIndex('name', 'name', { unique: false });
objectStore.createIndex('email', 'email', { unique: true });
}
}
}
const userDB = new UserDB();
userDB.open().then(() => {
return userDB.add('users', { name: 'John', age: 30, email: 'john@example.com' });
}).then((id) => {
console.log('User added with ID:', id);
});面试常见问题
1. Cookie、LocalStorage和SessionStorage的区别?
- Cookie: 容量小(4KB),可设置过期时间,每次请求都会发送
- LocalStorage: 容量大(5-10MB),永久存储,不发送到服务器
- SessionStorage: 容量大(5-10MB),会话结束清除,不发送到服务器
2. IndexedDB的特点?
- 大容量存储
- 异步API
- 支持事务
- 支持索引
- 支持复杂查询
3. 如何监听LocalStorage变化?
javascript
window.addEventListener('storage', (event) => {
console.log('Key:', event.key);
console.log('Old Value:', event.oldValue);
console.log('New Value:', event.newValue);
});4. Cookie的属性有哪些?
- expires: 过期时间
- max-age: 最大存活时间
- domain: 域名
- path: 路径
- secure: 安全标志
- HttpOnly: 防止XSS
- SameSite: 防止CSRF
5. 如何选择存储方式?
- Cookie: 会话管理、个性化
- LocalStorage: 长期存储、用户设置
- SessionStorage: 临时存储、表单数据
- IndexedDB: 大数据、离线应用
通过理解浏览器存储机制,可以更好地管理应用数据和优化用户体验。