作用
- 一种持久化方式数据的存储,HTML5新增的内容
- IE8+和标准浏览器支持,移动端可以放心使用
- cookie存储量小,4k,localStorage可以高达10M左右
- 在相同的域名和端口号下页面,可以共享localStorage中的数据.
- 存入localStorage中的数据,除非你主动删除,否则一直都在.
💡 注意:都是以字符串的形式来存储数据的.
用处
- 登录完成后
token
的存储 - 用户部分信息的存储,比如
昵称、头像、简介
- 一些项目通用参数的存储,例如
某个id、某个参数params
- 项目状态管理的持久化,例如
vuex的持久化、redux的持久化
- 项目整体的切换状态存储,例如
主题颜色、icon风格、语言标识
缺陷
-
1、命名过于简单
- 1、比如我们存用户信息会使用
user
作为 key 来存储 - 2、存储主题的时候用
theme
作为 key 来存储 - 3、存储令牌时使用
token
作为 key 来存储
💡 同源的两个项目,它们的localStorage是互通的。
举个例子比如 现在有两个项目,在同源 URL下,两个项目都需要往localStorage中存储一个 key 为name的值,那么这就会造成两个项目的name互相顶替的现象,也就是互相污染现象
- 1、比如我们存用户信息会使用
-
2、时效性
- localStorage:除非手动清除,否则一直存在
- sessionStorage:生命结束于当前标签页的关闭或浏览器的关闭
💡 其实普通的使用时没什么问题的,但是给某些指定缓存加上特定的时效性,是非常重要的!
-
3、隐秘性
- 点击Application就可以看到,localStorage的内容
💡 做
状态管理持久化
时,需要把数据先存在localStorage
中,这个时候就很有必要对缓存进行加密了
解决方案
- 命名规范
- 项目名 + 当前环境 + 项目版本 + 缓存key (根据需求自己调整)
- expire定时
- 设置缓存
key
时,将value
包装成一个对象,对象中有相应的时效时段
, - 当下一次想获取缓存值时,判断有无超时,不超时就获取
value
,超时就删除这个缓存
- 设置缓存
- crypto加密
- 加密很简单,直接使用crypto-js进行对数据的加密,使用这个库里的encrypt、decrypyt进行加密、解密
方法
-
add/edit
// 基础变量 // 方式一 . localStorage.cb = "城邦"; // 方式二 [] localStorage["xk"] = "小可"; // 方式三 setItem("属性名/变量","值/变量"); var stu = "赵莉"; var age = 18; localStorage.setItem(stu,age); console.log((localStorage["赵莉"])); // 引用变量 var stuStr = JSON.stringify(stu); localStorage.stu = stuStr;
-
get
// 基础变量 // 方式一 . localStorage.cb; // 方式二 [] localStorage["赵莉"]; // 方式三 getItem("属性名"/变量名) localStorage.getItem("a”); // 引用变量 var stuStr = localStorage.stu; var oStu = JSON.parse(stuStr);
-
delet
// 方式一 delete delete localStorage.cb; // 方式二 removeItem("属性名"/变量名) localStorage.removeItem("赵莉"); // 清空 localStorage.clear();
-
length
// 只读属性,赋值没有效果 localStorage.length = 1;
-
遍历
for (var key in localStorage) { console.log(key,localStorage[key],localStorage.getItem(key)); };
localStorage 存储的键值采用什么字符编码?
- localStorage 存储的键和值始终采用 UTF-16 DOMString 格式,每个字符使用两个字节。与对象一样,整数键将自动转换为字符串。
5M?
- 字符的长度 或 utf-16编码单元 或 10M字节空间
// 字符的个数,并不等于字符的长度
"a".length // 1
"人".length // 1
"𠮷".length // 2
"🔴".length // 2
- 而根据 UTF-16编码规则,要么2个字节,要么四个字节,
所以不如说是 10M 的字节数,更为合理。
当然,2个字节作为一个utf-16的字符编码单元,也可以说是 5M 的utf-16的编码单元。
- utf-16字符串计算字节数的方法:判断码点决定是2还是4
function sizeofUtf16Bytes(str) {
var total = 0,
charCode,
i,
len;
for (i = 0, len = str.length; i < len; i++) {
charCode = str.charCodeAt(i);
if (charCode <= 0xffff) {
total += 2;
} else {
total += 4;
}
}
return total;
}
// 留下8个字节数作为key,8个字节可是普通的4个字符换,也可是码点大于65535的3个字符,也可是是组合
// aaaa
// aa🔴
// 🔴🔴
const charTxt = "人";
let count = (10 * 1024 * 1024 / 2) - 8 / 2;
let content = new Array(count).fill(charTxt).join("");
const key = "aa🔴";
localStorage.clear();
try {
localStorage.setItem(key, content);
} catch (err) {
console.log("err", err);
}
const sizeKey = sizeofUtf16Bytes(key);
const contentSize = sizeofUtf16Bytes(content);
console.log("key size:", sizeKey, content.length); // key size: 8 5242876
console.log("content size:", contentSize, content.length); // content size: 10485752 5242876
console.log("total size:", sizeKey + contentSize, content.length + key.length); // total size: 10485760(10M) 5242880
localStorage 键占不占存储空间?
- 占空间
// key和val各自设置长 2.5M的长度
const charTxt = "a";
let count = (2.5 * 1024 * 1024);
let content = new Array(count).fill(charTxt).join("");
const key = new Array(count).fill(charTxt).join("");
localStorage.clear();
try {
console.time("setItem")
localStorage.setItem(key, content);
console.timeEnd("setItem")
} catch (err) {
console.log("err code:", err.code);
console.log("err message:", err.message)
}
// 把content的长度加1, 变为 2.5 M + 1, key的长度依旧是 2.5M的长度
// 超出存储空间
const charTxt = "a";
let count = (2.5 * 1024 * 1024);
let content = new Array(count).fill(charTxt).join("") + 1;
const key = new Array(count).fill(charTxt).join("");
localStorage.clear();
try {
console.time("setItem")
localStorage.setItem(key, content);
console.timeEnd("setItem")
} catch (err) {
console.log("err code:", err.code);
console.log("err message:", err.message)
}
键的数量,对读写的影响
- 键的数量对读取性能有影响,但是不大。
- 值的大小对性能影响更大,不建议保存大的数据。
// 500 * 1000键
let keyCount = 500 * 1000;
localStorage.clear();
for (let i = 0; i < keyCount; i++) {
localStorage.setItem(i, "");
}
setTimeout(() => {
console.time("save_cost");
localStorage.setItem("a", "1");
console.timeEnd("save_cost");
}, 2000)
setTimeout(() => {
console.time("read_cost");
localStorage.getItem("a");
console.timeEnd("read_cost");
}, 2000)
// save_cost: 0.05615234375 ms
// read_cost: 0.008056640625 ms
// 单独执行
localStorage.clear();
console.time("save_cost");
localStorage.setItem("a", "1");
console.timeEnd("save_cost");
// save_cost: 0.033203125 ms
- 保存的值表较大
const charTxt = "a";
const count = 5 * 1024 * 1024 - 1
const val1 = new Array(count).fill(charTxt).join("");
setTimeout(() =>{
localStorage.clear();
console.time("save_cost_1");
localStorage.setItem("a", val1);
console.timeEnd("save_cost_1");
},1000)
setTimeout(() =>{
localStorage.clear();
console.time("save_cost_2");
localStorage.setItem("a", "a");
console.timeEnd("save_cost_2");
},1000)
// save_cost_1: 12.276123046875 ms
// save_cost_2: 0.010009765625 ms
- 单次值的大小对存的性能影响非常大,读取也一样
- 尽量不要保存大的值,因为其是同步读取,纯大数据,用indexedDB
localStorage 功能检测
function storageAvailable(type) {
var storage;
try {
storage = window[type];
var x = '__storage_test__';
storage.setItem(x, x);
storage.removeItem(x);
return true;
}
catch(e) {
return e instanceof DOMException && (
// everything except Firefox
e.code === 22 ||
// Firefox
e.code === 1014 ||
// test name field too, because code might not be present
// everything except Firefox
e.name === 'QuotaExceededError' ||
// Firefox
e.name === 'NS_ERROR_DOM_QUOTA_REACHED') &&
// acknowledge QuotaExceededError only if there's something already stored
(storage && storage.length !== 0);
}
}
if (storageAvailable('localStorage')) {
// Yippee! We can use localStorage awesomeness
}
else {
// Too bad, no localStorage for us
}
localStorage已使用空间统计
function sieOfLS() {
return Object.entries(localStorage).map(v => v.join('')).join('').length;
}
localStorage.clear();
localStorage.setItem("🔴", 1);
localStorage.setItem("🔴🔴🔴🔴🔴🔴🔴🔴", 1111);
console.log("size:", sieOfLS()) // 23
// 🔴*9 + 1 *5 = 2*9 + 1*5 = 23
Notion – The all-in-one workspace for your notes, tasks, wikis, and databases.https://serious-lose.notion.site/localStorage-78d018365e6b442ba6dc77874f7823ee