第8章 HTML5中的数据存储
之前通常使用Cookie存储机制将数据保存在用户的客户端。
H5增加了两种全新的数据存储方式:Web Stroage和Web SQL Database.
前者用于临时或永久保存客户端少量数据,后者是客户端本地化的一套数据库系统。
8.1 Web Storage存储简介
Web Storage API分为会话数据和长期数据,相应的API分为两类:
sessionStorage(保存会话数据)
localStorage(在客户端长期保存数据)
整体优于Cookie方式。
8.1.1 sessionStorage对象
保存数据短暂,打开浏览器时可以查看操作过程中临时保存的数据,一旦关闭浏览器,所有sessionStorage对象保存的数据将全部丢失。一下是调用方法:
- sessionStorage.setItem(key,value):key表示保存内容的键名,value是键值,名不能重复。
- sessionStorage.getItem(key):返回指定键名对应的键值,若不存在则返回null。
1.功能描述
页面中,创建一个文本框与读取按钮,用户在文本框中输入内容时,通过sessionStorage对象保存文本框输入的内容,及时显示在页面中,单击读取按钮时,将直接读取被保存的临时数据。
2.实现代码
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>使用sessionStorage对象保存与读取临时数据</title>
<script>
function txtNameChange(v) {
var strName = v.value;
//保存数据
sessionStorage.setItem("strName",strName);
var pStatus = document.getElementById("pStatus");
pStatus.style.display="block";
pStatus.innerHTML=sessionStorage.getItem("strName");
}
function btnGetValue(){
var pStatus = document.getElementById("pStatus");
pStatus.style.display="block";
pStatus.innerHTML=sessionStorage.getItem("strName");
}
</script>
</head>
<body>
<fieldset>
<legend>sessionStorage对象保存与读取临时数据</legend>
<input type="text" name="txtName" class="inputTxt"
size="30px" onchange="txtNameChange(this);" />
<input type="button" name="btnGetValue" class="inputbtn"
onclick="btnGetValue();" value="读取"/>
<p id="pStatus"></p>
</fieldset>
</body>
</html>
3.页面效果
刷新后,还可以读到,但是关闭浏览器,进来,无法读到。
8.1.2 localStorage对象
sessionStorage只能保存临时会话数据,关闭浏览器后,数据清空。
如果需要长期在客户端保存数据,建议用localStorage对象,直至人工清除为止。
对应的方法:
- localStorage.setItem(key,value):同sessionStorage.
- localStorage.getItem(key):同sessionStorage.
- localStorage.removeItem(key):key表示要删除的键名,一旦删除,与键名相应的数据全部被删除。
1.功能描述
新建登录页面,用户在文本框中输入用户名与密码,单击登录按钮后,将使用localStorage对象保存登录时的用户名,如果选中是否保存密码,则保存密码,否则清空原先保存的密码,重新打开浏览器,将保存的用户名和密码数据分别显示在文本框中。
2.代码实现
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>使用localStorage对象保存与读取登录用户名与密码</title>
<style>
* {
list-style-type: none;
}
.status {
background-color: dodgerblue;
border: 1px solid;
color: white;
}
</style>
<script>
function $$(id) {
return document.getElementById(id);
}
//页面加载时调用的函数
function pageload() {
var strName = localStorage.getItem("keyName");
var strPass = localStorage.getItem("keyPass");
if (strName) {
$$("txtName").value = strName;
}
if (strPass) {
$$("txtPass").value = strPass;
}
}
//单击登录按钮后调用的函数
function btnLogin() {
var strName = $$("txtName").value;
var strPass = $$("txtPass").value;
localStorage.setItem("keyName", strName);
if ($$("chkSave").checked) {
localStorage.setItem("keyPass", strPass);
} else {
localStorage.removeItem("keyPass");
}
$$("spnStatus").className = "status";
$$("spnStatus").innerHTML = "登录成功!";
}
</script>
</head>
<body onload="pageload();">
<form action="#" id="frmLogin">
<fieldset>
<legend><!-- 字段说明 -->
登录
</legend>
<ul>
<li class="li_top">
<span id="spnStatus"></span>
</li>
<li>名称:<input type="text" id="txtName" class="inputTxt" /></li>
<li>密码:<input type="password" id="txtPass" class="inputTxt" /></li>
<li><input type="checkbox" id="chkSave" />是否保存密码</li>
<li class="li_bot">
<input type="button" class="inputbtn" value="登录" onclick="btnLogin();" />
<input type="reset" class="inputbtn" value="取消" />
</li>
</ul>
</fieldset>
</form>
</body>
</html>
3.页面效果
注意:尽管localStorage对象可以将数据长期保存在客户端,但是跨浏览器读取数据时,被保存的数据不可共用。
8.2 localStorage详解
8.2.1 清空localStorage数据
上面学的removeItem()只能单挑删除,想要清空所有保存的数据用clear().
1.功能描述
新建页面中添加两个按钮,使用localStorage对象保存6条顺序记录,另一个用于清空记录。
2.实现代码
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>清空localStorage对象保存的全部数据</title>
<script>
function $$(id) {
return document.getElementById(id);
}
var intNum = 0;
//单击增加按钮时调用
function btnAdd() {
for (var i = 0; i < 6; i++) {
localStorage.setItem("strKeyName" + i, "strKeyValue" + i);
intNum++;
}
$$("pStatus").innerHTML = "已成功保存<b>" + intNum + "</b>条数据记录!";
}
//单击清空按钮
function btnDel() {
localStorage.clear();
$$("pStatus").innerHTML = "已成功清空全部数据记录!";
}
</script>
</head>
<body>
<input id="btnAdd" type="button" value="增加" class="inputbtn" onclick="btnAdd();" />
<input id="btnDel" type="button" value="清空" class="inputbtn" onclick="btnDel();" />
<p id="pStatus"></p>
</body>
</html>
3.页面效果
8.2.2 遍历localStorage数据
为了查看所有保存的数据信息,通常要遍历这些数据,遍历过程中,需要访问另外两个属性:
length与key,前者是总数,后者是键名项,常与索引号index配合。
1.功能描述
创建页面,通过遍历获取对象保存的全部点评数据记录,在文本框中输入点评内容,单击发表后,可以通过localStorage对象保存输入的数据,并实时显示到页面中。
2.实现代码
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>遍历localStorage数据</title>
<style>
span {
display: inline-block;
width: 100px;
margin: 0 10px;
}
</style>
<script>
function $$(id) {
return document.getElementById(id);
}
//指定长度的随机数
function retRandomNum(n) {
var strRnd = "";
for (var i = 0; i < n; i++) {
strRnd += Math.floor(Math.random() * 10);
}
return strRnd;
}
//单击发表按钮调用
function btnAdd() {
//获取文本框的内容
var strContent = $$("txtContent").value;
//定义一个日期型对象
var strTime = new Date();
//如果不为空,则保存
if (strContent.length > 0) {
var strKey = "cnt" + retRandomNum(4);
var strVal = strContent + "," + strTime.toLocaleTimeString();
localStorage.setItem(strKey, strVal);
}
//重新加载
getLocalData();
//清空原先内容
$$("txtContent").value = "";
}
//获取保存数据并显示在页面中
function getLocalData() {
//标题部分
var strHTML = "<li><span>编号</span><span>内容</span><span>时间</span></li>";
//内容部分
var strArr = new Array();
for (var i = 0; i < localStorage.length; i++) {
//获取key值
var strKey = localStorage.key(i);
//过滤键名内容
if (strKey.substring(0, 3) == "cnt") {
var strVal = localStorage.getItem(strKey);
strArr = strVal.split(",");
strHTML += "<li><span>" + strKey + "</span>";
strHTML += "<span>" + strArr[0] + "</span>";
strHTML += "<span>" + strArr[1] + "</span></li>";
}
}
$$("ulMessage").innerHTML = strHTML;
}
</script>
</head>
<body onload="getLocalData();">
<ul id="ulMessage">正在读取数据...</ul>
<p class="p4">
<textarea id="txtContent" class="txtContent" cols="30" rows="10"></textarea><br />
<input id="btnAdd" type="button" value="发表" onclick="btnAdd();" />
</p>
</body>
</html>
3.页面效果
4.源码分析
随机数4位的取法关注一下,通过索引取key值小技巧用一下。
8.2.3 使用JSON对象存取数据
H5中可以通过localStorage数据与JSON对象互转,快速实现存储更多数据的功能。
转JSON对象方法:
- JSON.parse(data),data表示对象获取的数据,返回装载data数据的JSON对象。
- JSON.stringify(obj),将对象转为JSON格式的文本数据。
1.功能描述
创建一个简单的学生信息管理页面,用户输入姓名,分数,选择性别,单击增加按钮后,使用JSON中的stringify()方法,将数据保存在localStorage对象中,同时,调用JSON中的parse()方法实时显示新增学生数据信息。
2.实现代码
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>使用JSON对象存储数据</title>
<style>
ul span {
display: inline-block;
width: 100px;
margin: 0 10px;
}
</style>
<script>
function $$(id) {
return document.getElementById(id);
}
function btnAdd() {
var strStuID = $$("txtStuID").value;
var strName = $$("txtName").value;
var strSex = $$("selSex").value;
var strScore = $$("txtScore").value;
if (strName.length > 0 && strScore.length > 0) {
//定义1个实体对象,保存全部获取的值
var SetData = new Object();
SetData.StuID = strStuID;
SetData.Name = strName;
SetData.Sex = strSex;
SetData.Score = strScore;
var strTxtData = JSON.stringify(SetData);
localStorage.setItem(strStuID, strTxtData);
}
//重新加载
getLocalData();
//清空原先内容
$$("txtName").value = "";
$$("txtScore").value = "";
}
//获取保存数据并显示到页面上
function getLocalData() {
//标题部分
var strHTML = "<li><span>学号</span><span>姓名</span>" +
"<span>性别</span><span>总分</span></li>";
//内容部分
for (var i = 0; i < localStorage.length; i++) {
//获取key值
var strKey = localStorage.key(i);
//过滤键名内容
if (strKey.substring(0, 3) == "stu") {
var GetData = JSON.parse(localStorage.getItem(strKey));
strHTML += "<li><span>" + GetData.StuID + "</span>";
strHTML += "<span>" + GetData.Name + "</span>";
strHTML += "<span>" + GetData.Sex + "</span>";
strHTML += "<span>" + GetData.Score + "</span></li>";
}
}
$$("ulMessage").innerHTML = strHTML;
$$("txtStuID").value = "stu" + retRandomNum(4);
}
//指定长度的随机数
function retRandomNum(n) {
var strRnd = "";
for (var i = 0; i < n; i++) {
strRnd += Math.floor(Math.random() * 10);
}
return strRnd;
}
</script>
</head>
<body onload="getLocalData();">
<ul id="ulMessage">正在读取数据...</ul>
<p>
<span>学号:<input type="text" id="txtStuID" readonly size="10" /></span><br />
<span>姓名:<input type="text" id="txtName" size="10" /></span>
<span>性别:
<select id="selSex">
<option value="男">男</option>
<option value="女">女</option>
</select>
</span>
<br />
<span>总分:<input type="text" id="txtScore" size="10" /></span>
<p>
<input type="button" id="btnAdd" value="增加" onclick="btnAdd();" />
</p>
</p>
</body>
</html>
3.页面效果
4.源码分析
可以不借助后台数据来进行增删改查了。
8.2.4 管理localStorage数据
通过JSON对对象进行存取,还可以通过键名,查询、更新、删除对应的键值记录,真正实现对localStorage对象保存数据的管理功能。
1.功能描述
在8.1.3的基础上,添加输入查询内容的文本框与查询按钮,同时,在列表内容项中新增编辑和删除链接。单击查询按钮时,可以根据输入的学号,返回对应的记录,单击编辑与删除链接时,分别实现根据键名更新或者删除对应的键值数据。
2.实现代码
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>管理localStorage数据</title>
<style>
ul span {
display: inline-block;
width: 100px;
margin: 0 10px;
}
</style>
<script>
function $$(id) {
return document.getElementById(id);
}
function btnAdd() {
var strStuID = $$("txtStuID").value;
var strName = $$("txtName").value;
var strSex = $$("selSex").value;
var strScore = $$("txtScore").value;
if (strName.length > 0 && strScore.length > 0) {
//定义1个实体对象,保存全部获取的值
var SetData = new Object();
SetData.StuID = strStuID;
SetData.Name = strName;
SetData.Sex = strSex;
SetData.Score = strScore;
var strTxtData = JSON.stringify(SetData);
localStorage.setItem(strStuID, strTxtData);
}
//重新加载
getLocalData(0);
//清空原先内容
$$("txtName").value = "";
$$("txtScore").value = "";
}
//点击查询按钮调用
function btnSearch() {
//获取查询学号
var strSearch = $$("txtSearch").value;
//根据学号键名获取数据
getLocalData(strSearch);
}
//获取保存数据并显示到页面上
function getLocalData(s) {
//标题部分
var strHTML = "<li>请输入学号:<input type='text' id='txtSearch' size='22' />";
strHTML += "<input id='btnSearch' type='button' value='查询' onClick='btnSearch();' /></li>";
strHTML += "<li><span>学号</span><span>姓名</span>" +
"<span>性别</span><span>总分</span><span>操作</span></li>";
//内容部分
if (s) {
var SearchData = JSON.parse(localStorage.getItem(s));
strHTML += "<li><span>" + SearchData.StuID + "</span>";
strHTML += "<span>" + SearchData.Name + "</span>";
strHTML += "<span>" + SearchData.Sex + "</span>";
strHTML += "<span>" + SearchData.Score + "</span>";
strHTML += "<span><a href='#' onclick=EditData('" + SearchData.StuID + "')>编辑</a> | ";
strHTML += "<a href='#' onclick=DeleteData('" + SearchData.StuID + "')>删除</a></span></li>";
} else {
for (var i = 0; i < localStorage.length; i++) {
//获取key值
var strKey = localStorage.key(i);
//过滤键名内容
if (strKey.substring(0, 3) == "stu") {
var GetData = JSON.parse(localStorage.getItem(strKey));
strHTML += "<li><span>" + GetData.StuID + "</span>";
strHTML += "<span>" + GetData.Name + "</span>";
strHTML += "<span>" + GetData.Sex + "</span>";
strHTML += "<span>" + GetData.Score + "</span>";
strHTML += "<span><a href='#' onclick=EditData('";
strHTML += GetData.StuID;
strHTML += "');>编辑</a> | ";
strHTML += "<a href='#' onclick=DeleteData('";
strHTML += GetData.StuID;
strHTML += "');>删除</a></span></li>";
}
}
}
$$("ulMessage").innerHTML = strHTML;
$$("txtStuID").value = "stu" + retRandomNum(4);
}
//编辑链接
function EditData(k) {
//根据键值获取对应的数据
var EditData = JSON.parse(localStorage.getItem(k));
$$("txtStuID").value = EditData.StuID;
$$("txtName").value = EditData.Name;
$$("selSex").value = EditData.Sex;
$$("txtScore").value = EditData.Score;
}
//删除链接
function DeleteData(k) {
localStorage.removeItem(k);
//重新加载
getLocalData(0);
}
//指定长度的随机数
function retRandomNum(n) {
var strRnd = "";
for (var i = 0; i < n; i++) {
strRnd += Math.floor(Math.random() * 10);
}
return strRnd;
}
</script>
</head>
<body onload="getLocalData(0);">
<ul id="ulMessage">正在读取数据...</ul>
<p>
<span>学号:<input type="text" id="txtStuID" readonly size="10" /><br />
<span>姓名:<input type="text" id="txtName" size="10" /></span>
<span>性别:
<select id="selSex">
<option value="男">男</option>
<option value="女">女</option>
</select>
</span>
<br />
<span>总分:<input type="text" id="txtScore" size="10" /></span>
<p>
<input type="button" id="btnAdd" value="增加" onclick="btnAdd();" />
<input type="button" id="clear" value="清除全部" onclick="localStorage.clear();" />
</p>
</p>
</body>
</html>
3.页面效果
8.3 Web SQL数据库基础(不推荐使用,推荐IndexedDB)
Web Storage只有5MB,键值存储带来诸多不便,除此之外还有WebSQL数据库,WebDB,内置了SQLite数据库,对数据库操作可以通过调用executeSql()方法实现,允许JS控制数据库的操作。
WebDB可以实现数据的本地存储,它提供了关系数据库的基本功能,可以存储页面交互的复杂数据,也能缓存从服务器获取的数据。通过事务驱动,实现对数据的管理,也支持多浏览器的并发操作。
核心方法
以下是规范中定义的三个核心方法:
- openDatabase:这个方法使用现有的数据库或者新建的数据库创建一个数据库对象。
- transaction:这个方法让我们能够控制一个事务,以及基于这种情况执行提交或者回滚。
- executeSql:这个方法用于执行实际的 SQL 查询。
打开数据库
我们可以使用 openDatabase() 方法来打开已存在的数据库,如果数据库不存在,则会创建一个新的数据库,使用代码如下:
var db = openDatabase('mydb', '1.0', 'Test DB', 2 * 1024 * 1024);
openDatabase() 方法对应的五个参数说明:
- 数据库名称
- 版本号
- 描述文本
- 数据库大小
- 创建回调
第五个参数,创建回调会在创建数据库后被调用。
执行查询操作
执行操作使用 database.transaction() 函数:
var db = openDatabase('mydb', '1.0', 'Test DB', 2 * 1024 * 1024); db.transaction(function (tx) { tx.executeSql('CREATE TABLE IF NOT EXISTS LOGS (id unique, log)'); });
插入数据
在执行上面的创建表语句后,我们可以插入一些数据:
var db = openDatabase('mydb', '1.0', 'Test DB', 2 * 1024 * 1024); db.transaction(function (tx) { tx.executeSql('CREATE TABLE IF NOT EXISTS LOGS (id unique, log)'); tx.executeSql('INSERT INTO LOGS (id, log) VALUES (1, "菜鸟教程")'); tx.executeSql('INSERT INTO LOGS (id, log) VALUES (2, "www.runoob.com")'); });
我们也可以使用动态值来插入数据:
var db = openDatabase('mydb', '1.0', 'Test DB', 2 * 1024 * 1024); db.transaction(function (tx) { tx.executeSql('CREATE TABLE IF NOT EXISTS LOGS (id unique, log)'); tx.executeSql('INSERT INTO LOGS (id,log) VALUES (?, ?)', [e_id, e_log]); });
实例中的 e_id 和 e_log 是外部变量,executeSql 会映射数组参数中的每个条目给 "?"。
读取数据
以下实例演示了如何读取数据库中已经存在的数据:
var db = openDatabase('mydb', '1.0', 'Test DB', 2 * 1024 * 1024);
db.transaction(function (tx) {
tx.executeSql('CREATE TABLE IF NOT EXISTS LOGS (id unique, log)');
tx.executeSql('INSERT INTO LOGS (id, log) VALUES (1, "菜鸟教程")');
tx.executeSql('INSERT INTO LOGS (id, log) VALUES (2, "www.runoob.com")');
});
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++){
alert(results.rows.item(i).log );
}
}, null);
});
完整实例
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, "菜鸟教程")');
tx.executeSql('INSERT INTO LOGS (id, log) VALUES (2, "www.runoob.com")');
msg = '<p>数据表已创建,且插入了两条数据。</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);
});
删除记录
删除记录使用的格式如下:
db.transaction(function (tx) { tx.executeSql('DELETE FROM LOGS WHERE id=1'); });
删除指定的数据id也可以是动态的:
db.transaction(function(tx) { tx.executeSql('DELETE FROM LOGS WHERE id=?', [id]);});
更新记录
更新记录使用的格式如下:
db.transaction(function (tx) { tx.executeSql('UPDATE LOGS SET log=\'www.w3cschool.cc\' WHERE id=2'); });
更新指定的数据id也可以是动态的:
db.transaction(function(tx) { tx.executeSql('UPDATE LOGS SET log=\'www.w3cschool.cc\' WHERE id=?', [id]); });
完整实例
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, "菜鸟教程")');
tx.executeSql('INSERT INTO LOGS (id, log) VALUES (2, "www.runoob.com")');
msg = '<p>数据表已创建,且插入了两条数据。</p>';
document.querySelector('#status').innerHTML = msg;
});
db.transaction(function (tx) {
tx.executeSql('DELETE FROM LOGS WHERE id=1');
msg = '<p>删除 id 为 1 的记录。</p>';
document.querySelector('#status').innerHTML = msg;
});
db.transaction(function (tx) {
tx.executeSql('UPDATE LOGS SET log=\'www.w3cschool.cc\' WHERE id=2');
msg = '<p>更新 id 为 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);
});