【JavaScript】离线应用与客户端存储
一、前言
这章非常重要,由于之后需要负责平台手机APP的日后维护,如何让用户在离线状态下正常使用,以及联网后的数据合并变得非常重要。
二、内容
离线检测
navigator.online —— 属性为true时表示设备能上网
online() —— 当网络从离线转在线触发
offline() —— 当网络从在线转离线触发 navigator.online取得初始状态,然后通过上述两个事件确定网络连接状态是否变化
数据存储
//Cookie
数量:每个域的cookie总数是有限的,一般每个域最多30~50个cookie
长度:整个cookie的长度限制在4095B以内 构成:
1.名称 URL编码
2.值 URL编码
3.域
4.路径 —— 指定域下的某个路径才能访问
5.失效时间
6.安全标志 —— 指定后cookie只有在使用SSL连接的时候才发送服务器 代码: var CookieUtil = { // 获取Cookie
get:function(name){
var cookieName = encodeURIComponent(name)+"=",
cookieStart = document.cookie.indexOf(cookieName),
cookieValue = null; if(cookieStart > -1){
var cookieEnd = document.cookie.indexOf(";",cookieStart);
if(cookieEnd == -1){
cookieEnd = document.cookie.length;
}
cookieValue = decodeURIComponent(document.cookie.substring(
cookieStart + cookieName.length, cookieEnd));
}
return cookieValue;
}, //设置Cookie
set:function(name, value, expires, path, domain, secure){
var cookieText = encodeURIComponent(name) + "=" + encodeURIComponent(value);
if(expires instanceof Date){
cookieText += "; expires=" + expores.toGMTString();
}
if(path){
cookieText += "; path=" + path;
}
if(domain){
cookieText += "; domain=" + domain;
}
if(secure){
cookieText += "; secure";
}
document.cookie = cookieText;
}, //删除Cookie
unset:function(name,path,domain,secure){
this.set{name, "", new Date(0), path, domain, secure};
}
} //子Cookie
使用cookie值来存储多个名称值对
name=name1=value1&name2=value2&name3=value3 总结:
1.cookie太大容易影响性能
2.不能在cookie中存储重要和敏感的数据
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//Web存储机制 —— Web Storage
1.提供一种在cookie之外存储会话数据的途径
2.提供一种存储大量可以跨会话存在的数据的机制 Storage类型,有以下方法:
clear() —— 删除所有值
getItem(name) —— 根据名称获得值
key(index) —— 获得index处的值的名字
removeItem(name) —— 删除由name指定的名值对
setItem(name,valie) —— 为指定的name设置一个对应值
sessionStorage对象
该对象存储特定与某个会话的数据,该数据只保存到浏览器关闭,它是Storage的一个实例 //使用方法存储数据
sessionStorage.setItem("name", "Nicholas");
//使用属性存储数据
sessionStorage.book = "Nicholas";
//遍历
for(var key in sessionStorage){
var value = sessionStorage.getItem(key);
} 用途:sessionStorage对象主要用于仅针对会话的小段数据的存储
globalStorage对象
用途:globalStorage对象主要用于跨越会话存储数据,但有特定的访问限制,需要指定域
globalStorage["wrox.com"]对象是Storage的一个实例
使用时一定要指定一个域名!!!
//保存数据
globalStorage["wrox.com"].name = "Nicholas"; //获取数据
var name = globalStorage["wrox.com"].name;
localStorage对象
它是Storage的一个实例不能给localStorage指定任何访问规则;规则事先就设定好了
要访问一个localStorage对象,页面必须来自同一域名(子域名无效),使用同一种协议,在同一端口上
相当于globalStorage[location.host] storage事件
在Storage对象进行任何修改,都会在文档上触发storage事件,有以下属性:
domain:发送变化的存储空间的域名
key:设置或删除的键名
newValue:如果是设置值,则是新值;如果是删除键,则是null
oldValue:键被更改之前的值
总结:
1.因浏览器不同而对存储空间大小有限制
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//IndexedDB —— 在浏览器保存结构化数据的一种数据库
IndexedDB设计的操作完全是异步进行的
差不多每一次IndexedDB操作,都需要注册onerror或onsuccess事件
var indexedDB = window.indexedDB || windows.msIndexedDB || window.mozIndexedDB || window.webkitIndexedDB; 1.数据库
var request, database;
request = indexedDB.open("admin"); //传入数据库名称
request.onerror = function(event){
alert("open fail" + event.target.errorCode); //出现错误
};
request.onsucess = function(event){
database = event.target.result; //得到数据库实例
}; 默认情况下,IndexedDB数据库是没有版本号的,最好一开始就指定
if(database.version != "1.0"){
request = database.setVersion("1.0");
request.onerror = function(event){};
request.onsuccess = function(event){};
}else{}
2.对象存储空间
数据库建立连接后,下一步是使用对象存储空间。
如果数据库的版本与传入的版本不匹配,那么可能需要创建一个新的对象存储对象。
假设一条记录的对象如下所示:
var user = {
username:"007",
firstName:"James",
lastName:"Bond",
password:"foo"
}; var store = db.createObjectStore("users",{keyPath:"username"}); //指定空间名称及keyPath作为键
//使用add()或put()添加数据 —— store.add() / store.put()
//其中add()方法重写会返回错误,put()重写原有对象没问题
3.事务
创建完对象存储空间之后,接下来所有操作都是通过事务来完成的
调用transaction()创建事务
var transaction = db.transaction();
//或
var transaction = db.transaction("users"); //访问一个对象
//或
var transaction = db.transaction("users","anotherStore"); //访问多个对象 上述方法都是以只读方式访问数据,如果修改访问方式:
var IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction;
var transaction = db.transaction("users",IDBTransaction.READ_WRITE);
其中:
IDBTransaction.READ_ONLY —— 只读
IDBTransaction.READ_WRITE —— 读写
IDBTransaction.VERSION_CHANGE —— 改变 使用objectStore()并传入存储空间的名称就可以访问特定的存储空间:
var request = db.transaction("users").objectStore("users").get("007");
request.onerror = function(event){
//do something
}
request.onsuccess = function(event){
var result = event.target.result;
alert(result.firstName);
}
事件本身也有事件处理程序:
transaction.onerror = function(event){//整个事务都被取消};
transaction.oncomplete = function(event){
//整个事务都成功完成,但访问不到event中的任何数据,
//必须在相应请求的onsuccess事件中才能访问
};
4.使用游标查询
检索多个对象时,需要在事务内创建游标 openCursor()
var store = db.transaction("users").objectStore("users"),
request = store.openCursor();
request.onerror = function(event){};
request.onsuccess = function(event){
var cursor = event.target.result; //返回一个IDBCursor实例
if(cursor){ //必须要检查
//do something
}
};
IDBCursor属性包含:
direction —— 游标移动方向
IDBCursor.NEXT(0) 下一项
IDBCursor.NEXT_NO_DUPLICATE(1) 下一个不重复项
IDBCursor.PREV(2) 前一项
IDBCursor.PREV_NO_DUPLICATE 前一个不重复项
key —— 对象的键
value —— 实际的对象,显示前需要使用JSON.stringify(value)来转成Json对象
primaryKey —— 游标使用的键 游标可以更新个别的记录 —— cursor.update() request.onsuccess = function(event){
var cursor = event.target.result,
value,
updateRequest;
if(cursor){
if(cursor.key == "foo"){
value = cursor.value;
value.password = "magic!"; updateRequest = cursor.update(value); //请求保存更新
udpateRequest.onsuccess = function(){//处理成功};
udpateRequest.onerror = function(){//处理成功};
}
}
}
游标也可以调用cursor.delete()删除相应记录,
如果当前事务没有修改对象存储空间的权限,update()与delete()会抛出错误 默认情况下,每个游标只发起一次请求,要想发起另一次请求,可以调用:
continue(key) —— 移动到结果集中的下一项
advance(count) —— 向前移动count指定的项数
5.键范围
单纯通过游标查询数据的方式太有限,键范围增加了灵活性
var IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange; only():
var onlyRange = IDBKeyRange.only("007"); lowerBound():
var lowerRange = IDBKeyRange.lowerBound("007"); //从007开始到最后,包含007
var lowerRange = IDBKeyRange.lowerBound("007",true); //从007开始到最后,不包含007
upperBound():
var upperRange = IDBKeyRange.upperBound("007"); //从007开始往上,包含007
var upperRange = IDBKeyRange.upperBound("007",true); //从007开始往上,不包含007
Bound():
var boundRange = IDBKeyRange.bound("下界键","上界键",是否跳过下界,是否跳过上界); 例:
var store = db.transaction("users").objectStore("users");
range = IDBKeyRange.bound("007","ace");
request = store.openCursor(range);
request.onsuccess = function(event){
var cursor = event.target.result;
if(cursor){};
}
6.设定游标方向
var IDBCursor= window.IDBCursor || window.webkitIDBCursor; var store = db.transaction("users").objectStore("users"),
request = store.openCursor(null, IDBCursor.NEXT_NO_DUPLICATE);//null为默认全范围 7.索引
对于某些数据,可能要为一个对象存储空间指定多个键,即主键与索引键
首先引用对象存储空间,然后调用createIndex() var store = db.transaction("users").objectStore("users"),
index = store.createIndex("username","username",{unique:false}); //其它空间也有可能含username 第一个参数:索引的名称
第二个参数:索引的属性的名字
第三个参数:是否在所有记录中唯一 使用一个已经存在的名为"username"的索引:
var store = db.transaction("users").objectStore("users");
index = store.index("username");
request = index.openCursor();
//如果只返回每条记录主键的游标:
request = index.openKeyCursor(); request.onsuccess = function(event){
//event.result.key中保存索引键
//event.result.value保存主键
}; //get()方法能够从索引中取得一个对象
request = index.get("007");
//要根据给定的索引键取得主键,使用getKey()
request = index.getKey("007"); IDBIndex对象含以下属性:
name —— 索引的名称
keyPath —— 传入createIndex()中的属性路径
objectStore —— 索引的对象存储空间
unique —— 标识索引键是否唯一 store.indexNames能访问到为该空间建立的所有索引
store.deleteIndex("name")则可以根据索引的名称删除索引 8.并发问题
如果浏览器的两个不同的标签页打开了同一页面,那么一个页面试图更新另一个页面尚未
准备就绪的数据库问题就有可能发生。因此,只有当浏览器中仅有一个标签页使用数据库情况下,调用setVersion()才能完成操作 正确的方式:
刚打开数据库时,要记着指定onversionchange事件处理程序。当同一个来源的另一个标签页调用setVersion()时,就会执行这个回调:
var request, database;
request = indexedDB.open("admin");
request.onsuccess = function(event){
database = event.target.result;
database.onversionchange = function(){
database.close()
};
} 在你想要更新数据库的版本但另一个标签页已经打开数据库的情况下,要触发onblocked事件:
var request= database.setVersion("2.0");
request.onblocked = function(){
alert("Please close all other tabs");
};
request.onsuccess = function(){
//do something
};
总结:
1.不能跨域共享信息
2.大约5MB或50MB的空间限制
【JavaScript】离线应用与客户端存储的更多相关文章
- js-新兴的API,最佳实践,离线应用于客户端存储
离线应用于客户端存储: 1.离线检测:online以及offline事件,都是在window对象上触发 navigator.online为true的时候是表示设备能够上网 2.使用一个描述文件(man ...
- 《javascript高级程序设计》 第23章 离线应用与客户端存储
23.1 离线检测23.2 应用缓存23.3 数据存储 23.3.1 Cookie 23.3.2 IE 用户数据 23.3.3 Web 存储机制 23.3.4 IndexedDB 23.1 离线检 ...
- 离线应用与客户端存储(cookie storage indexedDB)
离线检测 HTML5定义一个属性:navigator.onLine的属性.这个属性值为true,表示设备在线,值为false,表示设备离线.为了更好的确定网络是否可用,HTML5还定义了两个事件.这两 ...
- JavaScript中离线应用和客户端存储(cookies、sessionStorage、localStorage)
一.离线应用 所谓离线web应用,就是在设备不能上网的情况下仍然可以运行的应用. 开发离线web应用需要几个步骤:首先,确保应用知道设备是否能上网,以便下一步执行正确的操作:然后,应用还必须能访问一定 ...
- HTML5离线应用与客户端存储
序言 本篇文章会详细介绍使用HTML5开发离线应用的步骤,以及本地存储与cookie的一些异同,最后利用上面所学例子来实现一个购物车场景. 使用HTML5离线存储的基本过程如下: 离线检测:首先要对设 ...
- 《JavaScript》web客户端存储
Web存储: 兼容IE8在内的所有主流浏览器,不兼容早期浏览器:支持大容量但非无限量 LocalStorage和sessionStorage是window对象的两个属性,这两个属性都代表同一个stor ...
- JavaScript权威指南--客户端存储
客户端存储web应用允许使用浏览器提供的API实现将数据存储在用户电脑上. 客户端存储遵循“同源策略”,因此不同站点的页面是无法读取对于存储的数据.而同一站点的不同的页面之间是可以互相共享存储数据的. ...
- JavaScript的客户端存储
一.前言: 客户端存储实际上就是Web浏览器的记忆功能,通过浏览器的API实现数据存储到硬盘: 二.存储的不同形式: 1.Web存储:localStorage 和 sessionStorage 代表同 ...
- js023-离线应用与客户端存储
js023-离线应用与客户端存储 本章内容: 进行离线检测 使用离线缓存 在浏览器中保存数据 23.1 离线检测 第一步:知道设备是在线还是离线:navigator.Online属性.该值为true表 ...
随机推荐
- 查询数据库所有表和字段及其注释(mysql)
#查询某个库所有表 select * from information_schema.TABLES where table_schema = '数据库' #查询某个库所有表的字段 select * f ...
- (原创)python发送邮件
这段时间一直在学习flask框架,看到flask扩展中有一个mail插件,所以今天就给大家演示如果发邮件. 首先我注册了一个163邮箱,需要开启smtp功能,因为咱们python发送邮件经过的是smt ...
- 我们一起学习WCF 第八篇回调函数
什么是回调函数? 一个简单的例子:小明想要在京东购买一件商品.他会登陆网站选好自己的商品.然后他把这件商品放在购物车,然后开始付钱(这个表示触发,不付钱不发货(排除货到付款)).然后京东的人员收到了小 ...
- commons fileupload上传报错
这个问题困扰我好久了一直没有找到解决方法,先记录下来. 生产环境(简称A)上老是出错,而测试环境(简称B)一切正常. 我们的框架是JAVA语言编写,基于struts1技术总监自己搭的框架,我在stru ...
- PostFix使用dovecot支持POP3/IMAP收信
PostFix只能够收发邮件,以及使用SMTP发送邮件,想要使用POP3/IMAP收信的话必须装其他软件,本文通过配置dovecot让邮件服务器支持POP3/IMAP收信.POP3/IMAP是一种收信 ...
- python基础数据类型补充
python_day_7 一. 今日主要内容: 1. 补充基础数据类型的相关知识点 str. join() 把列表变成字符串 列表不能再循环的时候删除. 因为索引会跟着改变 字典也不能直接循环删除.把 ...
- 使用phpMyAdmin管理网站数据库(创建、导入、导出…)
作为一名站长,最重视的就是网站的数据安全了.本节襄阳网站优化就来讲讲如何使用phpMyAdmin管理软件进行mysql数据库的管理,实现基本的数据库管理用户.数据库的创建.数据的导入和导出操作(网站备 ...
- Ryu学习总结(持续更新)
Ryu学习总结 该篇学习笔记,与其他分析Ryu控制器代码的笔记不同,主要按照程序的构成来进行分块总结,由于本人为新手入门,不能保证没有错误,如果发现错误,欢迎指教. 以下的内容主要来源: 源码 官方文 ...
- lxd&openstack-lxd源码剖析
lxd:https://linuxcontainers.org/lxd/,目标是融入到openstack体系被管理,像虚拟机一样被管理使用.从如下图可知,并非走的是libvirt-lxc路线,而是no ...
- Python基础灬文件常用操作
文件常用操作 文件内建函数和方法 open() :打开文件 read():输入 readline():输入一行 seek():文件内移动 write():输出 close():关闭文件 写文件writ ...