JavaScript 客户端存储与应用拓展
在前端开发中,数据的持久化存储是一个重要的话题。不同的存储方式适用于不同的场景,下面将详细介绍几种常见的客户端存储方法。
1. 旧示例的修改
在之前的示例中,
functionOne
需要进行修改,添加以下样式设置:
square.style.position = "relative";
square.style.left = "0";
原因是与示例 8 - 2 不同,新的状态方法和事件处理程序实际上会保留页面内的状态。这意味着从步骤一到步骤二所做的更改(将位置设置为绝对定位并移动
div
元素)必须在第一个函数中取消,才能真正恢复页面状态。
2. 使用 sessionStorage 进行客户端存储
2.1 问题描述
你希望轻松存储会话信息,而不会遇到与 cookie 相关的大小和跨页面污染问题,并且防止在浏览器刷新时丢失信息。
2.2 解决方案
使用新的 DOM 存储
sessionStorage
功能:
sessionStorage.setItem("name", "Shelley");
sessionStorage.city = "St. Louis";
// 获取数据
var name = sessionStorage.getItem("name");
var city = sessionStorage.city;
// 删除数据
sessionStorage.removeItem("name");
sessionStorage.clear();
2.3 讨论
cookie 的一个限制是它们是特定于域/子域的,而不是特定于页面的。例如,一个人在两个浏览器标签中打开同一个购物网站,在一个标签中向购物车添加了一些商品,然后决定不购买该商品并关闭该标签页,认为这样就可以确保该商品不在购物车中。但当在另一个打开的标签中点击结账选项时,可能会发现基于 cookie 的购物车已经从两个页面更新了,最终可能会购买到不想要的东西。
而
sessionStorage
则不同,它是特定于页面的,即“页面内发生的事情,留在页面内”。
以下是一个比较
sessionStorage
和 cookie 的示例:
<!DOCTYPE html>
<html dir="ltr" lang="en-US">
<head>
<title>Comparing Cookies and sessionStorage</title>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" >
<style>
div
{
background-color: #ffff00;
margin: 5px;
width: 100px;
padding: 1px;
}
</style>
<script>
window.onload = function() {
document.getElementById("set").onclick = setData;
document.getElementById("get").onclick = getData;
document.getElementById("erase").onclick = removeData;
}
// set data for both session and cookie
function setData() {
var key = document.getElementById("key").value;
var value = document.getElementById("value").value;
// set sessionStorage
var current = sessionStorage.getItem(key);
if (current) {
current += value;
} else {
current = value;
}
sessionStorage.setItem(key, current);
// set cookie
current = getCookie(key);
if (current) {
current += value;
} else {
current = value;
}
setCookie(key, current);
}
function getData() {
try {
var key = document.getElementById("key").value;
// sessionStorage
var value = sessionStorage.getItem(key);
if (!value) value = "";
document.getElementById("sessionstr").innerHTML = "<p>" + value + "</p>";
// cookie
value = getCookie(key);
if (!value) value = "";
document.getElementById("cookiestr").innerHTML = "<p>" + value + "</p>";
} catch(e) {
alert(e);
}
}
function removeData() {
var key = document.getElementById("key").value;
// sessionStorage
sessionStorage.removeItem(key);
// cookie
eraseCookie(key);
}
// set session cookie
function setCookie(cookie, value) {
var tmp = cookie + "=" + encodeURI(value) + ";path=/";
document.cookie = tmp;
}
// each cookie separated by semicolon;
function getCookie(key) {
var cookie = document.cookie;
var first = cookie.indexOf(key + "=");
// cookie exists
if (first >= 0) {
var str = cookie.substring(first, cookie.length);
var last = str.indexOf(";");
// if last cookie
if (last < 0) last = str.length;
// get cookie value
str = str.substring(0, last).split("=");
return decodeURI(str[1]);
} else {
return null;
}
}
// set cookie date to the past to erase
function eraseCookie (key) {
var cookieDate = new Date();
cookieDate.setDate(cookieDate.getDate() - 10);
var tmp = key + "= ; expires=" + cookieDate.toGMTString() + "; path=/";
document.cookie = tmp;
}
</script>
</head>
<body>
<form>
<label for="key"> Enter key:</label>
<input type="text" id="key" /> <br /> <br />
<label for="value">Enter value:</label>
<input type="text" id="value" /><br /><br />
</form>
<button id="set">Set data</button>
<button id="get">Get data</button>
<button id="erase">Erase data</button>
<div id="sessionstr"><p></p></div>
<div id="cookiestr"><p></p></div>
</body>
操作步骤如下:
1. 在 Firefox 3.5 及以上版本中加载示例页面。
2. 向同一个键值添加一个或多个项,然后点击“Get data”按钮。
3. 在新的标签窗口中打开同一页面,再次点击“Get data”按钮。可以看到,新标签窗口中 cookie 值仍然存在,因为 cookie 是会话特定的,直到关闭浏览器才会失效;而
sessionStorage
是特定于标签窗口的,不会跨标签窗口保留。
4. 在新标签窗口中,向键值添加更多项,再次点击“Get data”按钮。
5. 返回原始标签窗口,点击“Get data”按钮,可以看到第二个标签中添加的项在 cookie 中显示,但
sessionStorage
项不会显示。
6. 最后,在原始标签窗口中点击“Erase data”按钮,分别在原始窗口和第二个标签窗口中点击“Get data”按钮,注意观察 cookie 和
sessionStorage
的差异。
sessionStorage
对象目前在 Firefox 3.5 及以上版本、Safari 4.x 及以上版本和 IE 8 中得到支持。需要注意的是,浏览器删除 cookie 的菜单选项可能对
sessionStorage
没有影响,使用时要谨慎。
sessionStorage
和
localStorage
都是新的 DOM 存储规范的一部分,它们都是
window
对象的属性,可以全局访问,并且都是
Storage
对象的实现。对
Storage
对象原型的更改会影响
sessionStorage
和
localStorage
对象。
3. 创建 localStorage 客户端数据存储项
3.1 问题描述
你希望以一种方式对表单元素条目(或任何数据)进行备份,以便在浏览器崩溃、用户意外关闭浏览器或丢失 Internet 连接时,用户可以继续操作。
3.2 解决方案
如果数据量较小,可以使用 cookie,但在离线情况下这种策略不起作用。更好的方法是使用新的
localStorage
:
var value = document.getElementById("formelem").value;
if (value) {
localStorage.formelem = value;
}
// 恢复数据
var value = localStorage.formelem;
document.getElementById("formelem").value = value;
3.3 讨论
localStorage
和
sessionStorage
的对象接口相同,设置和获取数据的方法也类似:
| 操作 | sessionStorage | localStorage |
| ---- | ---- | ---- |
| 设置数据(使用 item 方法) |
sessionStorage.setItem("key", "value");
|
localStorage.setItem("key", "value");
|
| 设置数据(直接使用属性名) |
sessionStorage.keyName = "value";
|
localStorage.keyName = "value";
|
| 设置数据(使用 key 方法) |
sessionStorage.key(0) = "value";
|
localStorage.key(0) = "value";
|
| 获取数据(使用 item 方法) |
value = sessionStorage.getItem("key");
|
value = localStorage.getItem("key");
|
| 获取数据(直接使用属性名) |
value = sessionStorage.keyName;
|
value = localStorage.keyName;
|
| 获取数据(使用 key 方法) |
value = sessionStorage.key(0);
|
value = localStorage.key(0);
|
它们都支持
length
属性,用于提供存储项对的数量,以及
clear
方法(无参数),用于清除所有存储(但 Firefox 仅支持清除
localStorage
的存储)。此外,它们的作用域都基于 HTML5 源,即数据存储在一个域的所有页面中共享,但不跨协议(如
http
与
https
不同)或端口。
两者的区别在于数据存储的时间:
sessionStorage
对象仅在会话期间存储数据,而
localStorage
对象将数据永久存储在客户端,直到被明确删除。
sessionStorage
和
localStorage
对象还支持一个事件:
storage
事件。当对
localStorage
项进行更改时,该事件会在所有页面上触发,但不同浏览器对该事件的捕获位置不同:Firefox 可以在
body
或
document
元素上捕获,IE 可以在
body
上捕获,Safari 可以在
document
上捕获。
以下是一个更全面的示例,展示了如何使用
localStorage
备份表单条目:
<!DOCTYPE html>
<html dir="ltr" lang="en-US">
<head>
<title>localstore</title>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" >
<style>
</style>
<script>
window.onload = function() {
try {
var elems = document.getElementsByTagName("input");
// 捕获表单提交事件以清除存储
document.getElementById("inputform").onsubmit = clearStored;
for (var i = 0; i < elems.length; i++) {
if (elems[i].type == "text") {
// 恢复数据
var value = localStorage.getItem(elems[i].id);
if (value) elems[i].value = value;
// 绑定 onchange 事件处理程序
elems[i].onchange = processField;
}
}
} catch (e) {
alert(e);
}
}
// 存储字段值
function processField() {
localStorage.setItem(window.location.href, "true");
localStorage.setItem(this.id, this.value);
}
// 清除存储的字段值
function clearStored() {
var elems = document.getElementsByTagName("input");
for (var i = 0; i < elems.length; i++) {
if (elems[i].type == "text") {
localStorage.removeItem(elems[i].id);
}
}
}
</script>
</head>
<body>
<form id="inputform">
<label for="field1">Enter field1:</label> <input type="text" id="field1" />
<br /> <br />
<label for="field2">Enter field2:</label> <input type="text" id="field2"
/><br /><br />
<label for="field3">Enter field1:</label> <input type="text" id="field3" />
<br /> <br />
<label for="field4">Enter field1:</label> <input type="text" id="field4" />
<br /> <br />
<input type="submit" value="Save" />
</body>
操作步骤如下:
1. 当页面加载时,表单元素的
onchange
事件处理程序会被分配给
processField
函数,用于存储字段值。如果值已经存储,则会恢复到表单元素中。
2. 向表单字段中输入数据,但在点击提交按钮之前刷新页面。如果不使用
localStorage
,数据会丢失;而使用
localStorage
后,重新加载页面时,表单会恢复到刷新前的状态。
3. 当表单提交时,所有存储的表单数据会被清除。
不同浏览器为
localStorage
分配的大小不同,一些浏览器(如 Firefox)允许用户扩展
Storage
对象的限制。
localStorage
可用于离线工作,例如在表单示例中,可以将数据存储在
localStorage
中,并提供一个按钮,在连接到 Internet 时点击该按钮,将数据从
localStorage
同步到服务器端存储。
4. 使用关系型数据存储持久化数据
4.1 问题描述
你希望在客户端拥有比其他持久化存储方法(如
localStorage
)更复杂的数据存储,并且希望使用 SQL 技能。
4.2 解决方案
可以在客户端应用程序中使用 SQL,但有一些显著的限制。W3C Web SQL Database 工作草案支持在客户端使用关系型数据库(如 SQLite),但目前仅在 WebKit 浏览器(Safari 和 Chrome)和最新的 Opera(10.5)中提供支持。
创建数据库:
var db = openDatabase("dbname", "1.0", "Bird Database", 1024 * 1024);
在事务中创建表:
db.transaction(function(tx) {
tx.executeSQL('CREATE TABLE birdTable(birdid INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, birdname VARCHAR(20) NOT NULL)');
});
查询表:
db.transaction(function(tx) {
tx.executeSQL('SELECT * FROM birdTable', [], sqlFunction, sqlError);
});
var sqlFunction = function(tx, recs) {
var rows = recs.rows;
for (var i = 0; i < rows.length; i++) {
alert(recs.rows.item(i).text);
}
};
4.3 讨论
Web SQL Database 规范的实现有限,并且该规范目前在 W3C 受阻。只有 WebKit(Chrome 和 Safari)和 Opera 在这方面取得了一些进展,不能保证 Mozilla 或 Microsoft 会采用它。
使用客户端关系型数据库存在一些问题:
1.
安全问题
:在当前的应用程序中,客户端和服务器分别处理不同形式的安全问题,包括数据库安全和防止 SQL 注入。引入客户端关系型数据库支持会带来新的安全隐患。
2.
客户端存储负担
:每一项新的创新都会带来新的漏洞,增加浏览器的大小和复杂性,并在本地机器上存储各种数据。但大多数 JavaScript 应用程序并不需要创建像 Gmail 或类似 Photoshop 的绘图程序。
3.
技能分离
:在许多公司中,前端应用程序开发和服务器端开发可能由不同的团队负责。不熟悉关系型数据库管理的人可能会随意进行 SQL 事务操作,而关系型数据库应用程序开发是一项专业技能。
从实现角度来看,目前仅支持 SQLite,并且客户端 SQL 默认是异步的,这意味着应用程序在事务完成之前不会被阻塞,但也带来了一些挑战。
虽然这个概念很有趣,但在确定这项技术在 2010 年之后仍有发展前景之前,建议避免在生产环境中使用。
5. JavaScript 的广泛应用
JavaScript 是 Web 开发者应该学习的最重要的编程语言之一。与其他编程环境或语言相比,使用 JavaScript 开发应用程序非常简单,只需要一个浏览器和一个文本编辑工具。例如,创建一个简单的 HTML 文件:
<!DOCTYPE html>
<head>
<title>Blank</title>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" >
</head>
<body>
</body>
在
title
元素之后添加以下脚本:
<script>
alert("Wow, that was easy!");
</script>
在任何浏览器中打开该页面,就可以看到效果。
除了构建标准的 Web 应用程序,JavaScript 还是许多主要框架(如 Microsoft 的 Silverlight)和桌面开发环境(如 Adobe AIR)的重要组成部分。JavaScript 和 JSON 是 Apache 新的 CouchDB 的基础功能,CouchDB 具有支持 JSON 的数据库和查询引擎。
综上所述,JavaScript 在客户端存储和应用拓展方面具有重要的作用,不同的存储方式和应用场景可以根据具体需求进行选择。在使用过程中,要充分考虑各种存储方式的优缺点,确保数据的安全和有效使用。同时,随着技术的不断发展,JavaScript 的应用领域也在不断扩大,为开发者带来更多的可能性。
JavaScript 客户端存储与应用拓展
6. 客户端存储方式总结
为了更清晰地对比不同的客户端存储方式,下面以表格形式进行总结:
| 存储方式 | 支持浏览器 | 数据存储时间 | 作用域 | 安全问题 | 操作复杂度 | 适用场景 |
| ---- | ---- | ---- | ---- | ---- | ---- | ---- |
| sessionStorage | Firefox 3.5 及以上、Safari 4.x 及以上、IE 8 | 会话期间 | 特定于标签窗口 | 较低 | 简单 | 临时存储会话相关数据,如表单临时输入 |
| localStorage | Firefox 3.5 及以上、Safari 4.x 及以上、IE 8 | 永久,直到手动删除 | 同一域的所有页面 | 较低 | 简单 | 长期存储用户偏好设置、表单数据备份等 |
| Web SQL Database | WebKit 浏览器(Safari 和 Chrome)、Opera 10.5 | 永久,直到手动删除 | 同一域的所有页面 | 较高 | 复杂 | 需要使用 SQL 进行复杂数据操作的场景 |
从这个表格可以看出,不同的存储方式各有优缺点,开发者需要根据具体的应用场景来选择合适的存储方式。例如,如果只是临时存储一些表单数据,
sessionStorage
是一个不错的选择;如果需要长期保存用户的设置信息,
localStorage
更为合适;而对于需要进行复杂数据查询和操作的场景,Web SQL Database 可能更能满足需求,但要注意其安全性和兼容性问题。
7. 客户端存储操作流程梳理
下面通过 mermaid 流程图来梳理使用不同客户端存储方式的基本操作流程。
graph LR
classDef startend fill:#F5EBFF,stroke:#BE8FED,stroke-width:2px
classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px
classDef decision fill:#FFF6CC,stroke:#FFBC52,stroke-width:2px
A([开始]):::startend --> B{选择存储方式}:::decision
B -->|sessionStorage| C(设置数据):::process
B -->|localStorage| D(设置数据):::process
B -->|Web SQL Database| E(创建数据库):::process
C --> F(获取数据):::process
D --> G(获取数据):::process
E --> H(创建表):::process
F --> I(删除数据):::process
G --> J(删除数据):::process
H --> K(查询数据):::process
I --> L([结束]):::startend
J --> L
K --> L
这个流程图展示了使用
sessionStorage
、
localStorage
和 Web SQL Database 进行数据存储和操作的基本流程。首先需要选择合适的存储方式,然后根据不同的存储方式进行相应的操作,如设置数据、获取数据、删除数据等。对于 Web SQL Database,还需要先创建数据库和表,然后进行查询操作。
8. 实际应用案例分析
为了更好地理解不同客户端存储方式的应用,下面通过几个实际案例进行分析。
8.1 购物车数据存储
在一个电商网站的购物车功能中,需要存储用户添加到购物车的商品信息。如果使用
sessionStorage
,当用户关闭浏览器标签时,购物车数据会被清空;而使用
localStorage
,购物车数据会一直保留,直到用户手动清空或删除。示例代码如下:
// 使用 localStorage 存储购物车数据
function addToCart(productId, quantity) {
var cart = JSON.parse(localStorage.getItem('cart')) || {};
if (cart[productId]) {
cart[productId] += quantity;
} else {
cart[productId] = quantity;
}
localStorage.setItem('cart', JSON.stringify(cart));
}
function getCart() {
return JSON.parse(localStorage.getItem('cart')) || {};
}
function clearCart() {
localStorage.removeItem('cart');
}
在这个示例中,
addToCart
函数用于将商品添加到购物车,
getCart
函数用于获取购物车中的商品信息,
clearCart
函数用于清空购物车。通过
localStorage
,可以确保用户在不同时间访问网站时,购物车数据不会丢失。
8.2 表单数据备份
在一个用户注册表单中,为了防止用户因意外情况(如浏览器崩溃、网络中断)丢失已输入的数据,可以使用
localStorage
进行表单数据备份。示例代码如下:
<!DOCTYPE html>
<html>
<head>
<title>表单数据备份</title>
<script>
window.onload = function() {
var inputs = document.getElementsByTagName('input');
for (var i = 0; i < inputs.length; i++) {
var input = inputs[i];
var value = localStorage.getItem(input.name);
if (value) {
input.value = value;
}
input.addEventListener('input', function() {
localStorage.setItem(this.name, this.value);
});
}
document.getElementById('form').addEventListener('submit', function() {
for (var i = 0; i < inputs.length; i++) {
localStorage.removeItem(inputs[i].name);
}
});
};
</script>
</head>
<body>
<form id="form">
<label for="username">用户名:</label>
<input type="text" name="username"><br>
<label for="email">邮箱:</label>
<input type="email" name="email"><br>
<input type="submit" value="提交">
</form>
</body>
</html>
在这个示例中,当页面加载时,会从
localStorage
中获取已存储的表单数据并填充到表单中。当用户输入数据时,会将数据存储到
localStorage
中。当表单提交时,会清空
localStorage
中存储的表单数据。
9. 未来发展趋势展望
随着 Web 技术的不断发展,客户端存储技术也在不断演进。未来,可能会出现更安全、更高效、更易于使用的客户端存储方式。例如,W3C 正在不断完善相关的存储规范,以提高存储的兼容性和性能。同时,随着移动设备的普及,对客户端存储的需求也在不断增加,开发者需要更加关注不同设备和浏览器的兼容性问题。
另外,随着云计算和大数据技术的发展,客户端存储与服务器端存储的结合将更加紧密。例如,将一些常用的数据存储在客户端,而将大量的历史数据存储在服务器端,通过合理的数据同步机制,实现数据的高效利用和管理。
总之,JavaScript 的客户端存储技术在 Web 开发中扮演着重要的角色,开发者需要不断学习和掌握这些技术,以适应不断变化的技术环境和用户需求。通过合理选择和使用不同的客户端存储方式,可以提高应用程序的性能和用户体验,为用户提供更加优质的服务。
综上所述,JavaScript 在客户端存储和应用拓展方面有着丰富的技术和应用场景。开发者需要深入理解不同存储方式的特点和操作方法,结合实际应用需求,选择合适的存储方式,并注意其安全性和兼容性问题。同时,要关注客户端存储技术的未来发展趋势,不断提升自己的技术水平,以应对不断变化的 Web 开发挑战。
超级会员免费看

被折叠的 条评论
为什么被折叠?



