HTML5 存储
zKing 2019-01-07 HTML
摘要
HTNL5 中的存储主要使用来做本地存储
# Manifest
- 使用 HTML5,通过创建 cache manifest 文件,可以轻松地创建 web 应用的离线版本。
- 所谓的离线存储,即是应用程序的缓存
- manifest 文件是简单的文本文件,它告知浏览器被缓存的内容(以及不缓存的内容)。
manifest 文件可分为三个部分:
- CACHE MANIFEST - 在此标题下列出的文件将在首次下载后进行缓存,这个部分是必须的
- NETWORK - 在此标题下列出的文件需要与服务器的连接,且不会被缓存
- FALLBACK - 在此标题下列出的文件规定当页面无法访问时的回退页面(比如 404 页面)
<!DOCTYPE HTML>
<html manifest="demo.appcache">
.....
</html>
demo.appcache
CACHE MANIFEST
# 浏览器会从网站的根目录下载这三个文件。然后,无论用户何时与因特网断开连接,这些资源依然是可用的。
/theme.css
/logo.gif
/main.js
NETWORK:
# 规定文件 "login.php" 永远不会被缓存,且离线时是不可用的:
login.php
FALLBACK:
# 规定如果无法建立因特网连接,则用 "offline.html" 替代 /html5/ 目录中的所有文件:
/html/ /offline.html
注意
- 一旦文件被缓存,则浏览器会继续展示已缓存的版本,即使修改了服务器上的文件。为了确保浏览器更新缓存,需要更新 manifest 文件。
- 另外,浏览器对缓存数据的容量限制可能不太一样(某些浏览器设置的限制是每个站点 5MB)。
# LocalStorage
- HTML5 设计出来专门用于浏览器存储的,大小为 5 M 左右,仅在客户端使用,不和服务端进行通信
- 在浏览器的隐私模式下不能读取
- 本质是在读写文件,写入数据量大的话会卡(localstorage写入内存中的)
- 不能被爬虫读取
LocalStorage 的使用方法有以下几种
// 增加
localStorage.setItem("name", "value");
// 查看
localStorage.getItem("name");
// 修改
localStorage.name = "yourName";
// 删除单个
localStorage.removeItem("name");
// 删除全部
localStorage.clear();;
<body>
<div style="border: 2px dashed #ccc;width:320px;text-align:center;">
<label for="sitename">网站名(key):</label>
<input type="text" id="sitename" name="sitename" class="text"/>
<br/>
<label for="siteurl">网 址(value):</label>
<input type="text" id="siteurl" name="siteurl"/>
<br/>
<input type="button" onclick="save()" value="新增记录"/>
<hr/>
<label for="search_phone">输入网站名:</label>
<input type="text" id="search_site" name="search_site"/>
<input type="button" onclick="find()" value="查找网站"/>
<p id="find_result"><br/></p>
</div>
<br/>
<div id="list">
</div>
<script>
// 载入所有存储在localStorage的数据
loadAll();
//保存数据
function save(){
var siteurl = document.getElementById("siteurl").value;
var sitename = document.getElementById("sitename").value;
localStorage.setItem(sitename, siteurl);
alert("添加成功");
}
//查找数据
function find(){
var search_site = document.getElementById("search_site").value;
var sitename = localStorage.getItem(search_site);
var find_result = document.getElementById("find_result");
find_result.innerHTML = search_site + "的网址是:" + sitename;
}
//将所有存储在localStorage中的对象提取出来,并展现到界面上
function loadAll(){
var list = document.getElementById("list");
if(localStorage.length>0){
var result = "<table border='1'>";
result += "<tr><td>网站名</td><td>网址</td></tr>";
for(var i=0;i<localStorage.length;i++){
var sitename = localStorage.key(i);
var siteurl = localStorage.getItem(sitename);
result += "<tr><td>"+sitename+"</td><td>"+siteurl+"</td></tr>";
}
result += "</table>";
list.innerHTML = result;
}else{
list.innerHTML = "数据为空……";
}
}
</script>
一般使用JSON.stringify()
进行 JSON 格式化后再存入到 localStorage 中
localStorage是公共资源,存在着 XSS 注入的风险
# LocalStorage 设置过期时间
在将 WebApp 打包的时候,会发现一个问题——不能使用 cookie,这就只能使用 localstorage 来当作替代品。localstorage 本身是没有过期时间来设置的,所以只能迂回一下,想出一个替代方案
在设置 localstorage 的时候,先多设置一个
let today = Date.now()
let future = today + 1000 * 60 * 60 * 24 * 7 // 七天
localStorage.setItem('expire_login', future)
localStorage.setItem('id', 'id')
等需要取出的时候,再进行判断,即可删除
let today = Date.now()
let expire = localStorage.getItem('expire_login')
if (today > expire) { // 过期了
localStorage.removeItem('id')
localStorage.removeItem('expire_login')
}
# SessionStorage
- 会话级别的浏览器存储,大小为 5 M 左右,仅在客户端使用,不和服务端进行通信
- 接口封装较好,可以对于表单信息的维护
用法和 localStorage 一样,但是,有效期只有网页在浏览器打开到关闭的时间段
# IndexedDB
- IndexedDB 是一种低级API,用于客户端存储大量结构化数据(包括, 文件/ blobs)。该API使用索引来实现对该数据的高性能搜索。
- 虽然 Web Storage 对于存储较少量的数据很有用,但对于存储更大量的结构化数据来说,这种方法不太有用。
- IndexedDB提供了一个解决方案。
- 通俗地说,IndexedDB 就是浏览器提供的本地数据库,详情可以看这篇 文章
var db;
var request = window.indexedDB.open("myDB", "1.0"); // 创建数据库
request.onerror = function (event) {
console.log('数据库打开报错');
};
request.onsuccess = function (event) { // 连接成功
console.log('数据库打开成功');
//处理事件
add();
read();
};
request.onupgradeneeded = function (event) {
db = event.target.result;
var objectStore;
if (!db.objectStoreNames.contains('person')) { // 建表
objectStore = db.createObjectStore('person', {
keyPath: 'id'
});
objectStore.createIndex('name', 'name', {
unique: false
});
objectStore.createIndex('email', 'email', {
unique: true
});
}
};
function add() {
var transaction = db.transaction(['person'], 'readwrite');
var objectStore = transaction.objectStore('person');
var request = objectStore.add({
id: 1,
name: '张三',
email: 'zhangsan@example.com'
});
request.onsuccess = function (event) {
console.log('数据写入成功');
};
request.onerror = function (event) {
console.log('数据写入失败');
}
}
function read() {
var transaction = db.transaction(['person']);
var objectStore = transaction.objectStore('person');
var request = objectStore.get(1);
request.onerror = function (event) {
console.log('事务失败');
};
request.onsuccess = function (event) {
if (request.result) {
console.log('Name: ' + request.result.name);
console.log('Email: ' + request.result.email);
} else {
console.log('未获得数据记录');
}
};
}
# Web SQL
- Web SQL 数据库 API 并不是 HTML5 规范的一部分,但是它是一个独立的规范,引入了一组使用 SQL 操作客户端数据库的 APIs。
- 个人感觉 Web SQL 目前还有点不稳定
<body>
<div id="status" name="status">状态信息</div>
<script type="text/javascript">
var db = openDatabase('mydb', '1.0', 'Test DB', 2 * 1024 * 1024);
var msg;
db.transaction(function (tx) {
tx.executeSql('CREATE TABLE IF NOT EXISTS LOGS (id unique, log)');
tx.executeSql('INSERT INTO LOGS (id, log) VALUES (1, "Web SQL")');
tx.executeSql('INSERT INTO LOGS (id, log) VALUES (2, "www.zking.wang")');
msg = '<p>数据表已创建,且插入了2条数据。</p>';
document.querySelector('#status').innerHTML = msg;
});
db.transaction(function (tx) {
tx.executeSql('SELECT * FROM LOGS', [], function (tx, results) {
var len = results.rows.length, i;
msg = "<p>查询记录条数: " + len + "</p>";
document.querySelector('#status').innerHTML += msg;
for (i = 0; i < len; i++){
msg = "<p><b>" + results.rows.item(i).log + "</b></p>";
document.querySelector('#status').innerHTML += msg;
}
}, null);
});
</script>
</body>
# Service Workers
这个部分暂时没怎么接触,之后有空再更新。