H5 的浏览器存储
1、cookie
这个存储用了很久了,而且也是以前大多网站十分喜欢的存储站点。但是也很容易被清除。同时 cookie 会在每一次通信过程中传向服务端。同时 cookie 有一个很好的地 方就是,它本身有一个过期时间属性,可以用来标注一个变量的有效期(cookie.setMaxAge(60*60)
; // 过期时间为1小时)。而 cookie 一 旦过期就会被自动删除掉
cookie 重要的属性
属性 | 说明 |
---|---|
name=value | 键值对,设置 Cookie 的名称及相对应的值,都必须是字符串类型 - 如果值为 Unicode 字符,需要为字符编码。 - 如果值为二进制数据,则需要使用 BASE64 编码。 |
domain | 指定 cookie 所属域名,默认是当前域名 |
path | 指定 cookie 在哪个路径(路由)下生效,默认是 '/'。 如果设置为 /abc ,则只有 /abc 下的路由可以访问到该 cookie,如:/abc/read 。 |
maxAge | cookie 失效的时间,单位秒。如果为整数,则该 cookie 在 maxAge 秒后失效。如果为负数,该 cookie 为临时 cookie ,关闭浏览器即失效,浏览器也不会以任何形式保存该 cookie 。如果为 0,表示删除该 cookie 。默认为 -1。 - 比 expires 好用。 |
expires | 过期时间,在设置的某个时间点后该 cookie 就会失效。 一般浏览器的 cookie 都是默认储存的,当关闭浏览器结束这个会话的时候,这个 cookie 也就会被删除 |
secure | 该 cookie 是否仅被使用安全协议传输。安全协议有 HTTPS,SSL等,在网络上传输数据之前先将数据加密。默认为false。 当 secure 值为 true 时,cookie 在 HTTP 中是无效,在 HTTPS 中才有效。 |
httpOnly | 如果给某个 cookie 设置了 httpOnly 属性,则无法通过 JS 脚本 读取到该 cookie 的信息,但还是能通过 Application 中手动修改 cookie,所以只是在一定程度上可以防止 XSS 攻击,不是绝对的安全 |
eg:设置cookie: document.cookie = "key=value;"
setCookie(name,value,expiredays){//设置时间为天为过期单位
var exdate=new Date();
exdate.setDate(exdate.getDate()+expiredays);
document.cookie=name + '=' + escape(value)+((expiredays==null) ? "" : ";expires="+exdate.toGMTString())
},
获取cookie:
getCookie(name){
var start = document.cookie.indexOf(name+'=')
var end = document.cookie.indexOf(';',start)
if(end=-1){
end = document.cookie.length
}
return unescape(document.cookie.substring(start,end))
}
2、localStorage、sessionStorage
localStorage: 持久存储,只要用户不主动删除就会一直存在;
//设置localStorage保存到本地,第一个为变量名,第二个是值 localStorage.setItem('Author', 'Jane') // 获取数据 localStorage.getItem('Author') // 删除保存的数据 localStorage.removeItem('Author') // 清除所有保存的数据 localStorage.clear()
- sessionStorage:面向 session 的浏览器存储,因此只存在于一个页面的生命周期内,关闭即清除两者均采用键值对的形式存储数据
// 设置sessionStorage保存到本地,第一个为变量名,第二个是值
sessionStorage.setItem('sessionName', 'John')
// 获取数据
sessionStorage.getItem('sessionName')
// 删除保存的数据
sessionStorage.removeItem('sessionName')
// 清除所有保存的数据
sessionStorage.clear()
Web Storage带来的好处:
- 减少网络流量:一旦数据保存在本地之后,就可以避免再向服务器请求数据,因此减少不必要的数据请求,减少数据在浏览器和服务器间不必要的来回传递
- 快速显示数据:性能好,从本地读数据比通过网络从服务器上获得数据快得多,本地数据可以及时获得,再加上网页本身也可以有缓存,因此整个页面和数据都在本地的话,可以立即显示
- 临时存储:很多时候数据只需要在用户浏览一组页面期间使用,关闭窗口后数据就可以丢弃了,这种情况使用sessionStorage非常方便
3、indexedDB
内嵌在浏览器端的非关系型数据库,数据以键值对的形式存储,兼容性良好 indexDB 直接操作的存储对象是 ObjectStore,这有点类似其他数据库中 table 概念
打开数据库
const version = 1; // 版本主要用来控制数据库的结构,当数据库结构(表结构)发生变化时,版本也会变化
const dbName = "myData";
// 第一个参数是数据库的名字,第二个参数是数据库的版本号
const request = window.indexedDB.open(dbName, version);
let db; // 全局 IndexedDB 数据库实例
// onupgradeneeded 在版本改变时触发(首次连接数据库时,版本从 0 变成 1,因此也会触发,且先于 onsuccess)
request.onupgradeneeded = (event) => {
db = event.target.result;
};
// onsuccess 在连接成功后触发
request.onsuccess = (event) => {
db = request.result;
console.log("db connected");
};
// onerror 在连接失败时触发
request.onblocked = (event) => {
console.log("db request blocked!");
}
// onblocked 在连接被阻止的时候触发,比如打开版本低于当前存在的版本
request.onerror = (event) => {
console.log("error!");
};
创建数据表
eg:数据记录是{ id: 1, name: ‘张三’ },那么id属性可以作为主键。主键也可以指定为下一层对象的属性,比如{ foo: { bar: ‘baz’ } }的foo.bar也可以指定为主键。
request.onupgradeneeded = (event) => {
const db = event.target.result;
if (!db.objectStoreNames.contains("person")) {
// 创建数据表并设置id为自增主键
db.createObjectStore("person", {
"keyPath": "id", // 主键
"autoIncrement": true // 自增(每加一条数据,主键会自动增长,无需开发者指定)
});
}
};
添加数据
const transaction = db.transaction(["person"], "readwrite"); // 创建事务
const objectStore = transaction.objectStore("person"); // 指定person表
objectStore.add({
"name": "张三",
"age": 24,
"email": "zhangsan@example.com"
}); // 添加数据
transaction.oncomplete = (event) => {
console.log("数据写入成功");
};
transaction.onerror = (event) => {
console.log("数据写入失败");
};
获取数据
const transaction = db.transaction(["person"], "readonly");
const objectStore = transaction.objectStore("person");
const request = objectStore.get(1);
request.onerror = (event) => {
console.log("事务失败");
};
request.onsuccess = (event) => {
const result = event.target.result;
if (result) {
console.log("Name: " + result.name);
console.log("Age: " + result.age);
console.log("Email: " + result.email);
} else {
console.log("未获得数据记录");
}
};
遍历数据
const transaction = db.transaction(["person"], "readonly");
const objectStore = transaction.objectStore("person");
const request = objectStore.openCursor();
// penCursor()方法是一个异步操作,要监听success事件
request.onsuccess = (event) => {
const cursor = event.target.result;
if (cursor) {
console.log("Id: " + cursor.key);
console.log("Name: " + cursor.value.name);
console.log("Age: " + cursor.value.age);
console.log("Email: " + cursor.value.email);
cursor.continue()
} else {
console.log("没有更多数据了!");
}
};
更新数据
const transaction = db.transaction(["person"], "readwrite");
const objectStore = transaction.objectStore("person");
const request = objectStore.put({
"id": 1,
"name": "李四",
"age:" 35,
"email": "lisi@example.com"
}); // put()方法自动更新了主键为1的记录
request.onerror = (event) => {
console.log("数据更新失败");
};
request.onsuccess = (event) => {
console.log("数据更新成功");
};
删除数据
const transaction = db.transaction(["person"], "readwrite");
const objectStore = transaction.objectStore("person");
const request = objectStore.delete(1);
request.onerror = (event) => {
console.log("数据删除失败");
};
request.onsuccess = (event) => {
console.log("数据删除成功");
};
参考: indexDB API
4、flash cookie
主要利用了ShareObject类实现。flash cookie的好处是用户不易删除并且可以写入大量数据,但缺点是如果用户屏蔽掉了flash那就over了。
5、window 变量
生命周期有限,一般大家也不会去使用。但是对于全局变量的临时存储来说,还是一 个不可多得的好地方
6、websql
内嵌在浏览器的关系型数据库,前端可以像在使用 mysql、Oracle 一样的写 sql 语句, 并存储信息。兼容性良好。存储后可在浏览器 resource 中查看(废弃) 想了解
附:Localstorage、sessionStorage、cookie 的区别
共同点:保存在浏览器端、且同源的
区别:
1、存储地不同:
cookie 在浏览器和服务器间来回传递,而 sessionStorage 和 localStorage 不会自动把数据发送给服务器,仅在本地保存。 cookie 数据还有路径(path)的概念,可以限制 cookie 只属于某个路径下
2、存储大小不同:
- cookie 数据不能超过 4K,同时因为每次 http 请求都会携带 cookie、 所以 cookie 只适合保存很小的数据,如会话标识;
- sessionStorage 和 localStorage 虽然也有存 储大小的限制,但比 cookie 大得多,可以达到 5M 或更大 。
3、数据有效期不同:
- sessionStorage:仅在当前浏览器窗口关闭之前有效;
- localStorage:始终有效,窗口或浏览器关闭也一直保存,因此用作持久数据;
- cookie:只在设置的 cookie 过期时间之前有效,即使窗口关闭或浏览器关闭 。
4、作用域不同:
- sessionStorage 不在不同的浏览器窗口中共享,即使是同一个页面;
- localstorage 在所有同源窗口中都是共享的;
- cookie 也是在所有同源窗口中都是共享的。