您的位置:首页 > Web前端 > JavaScript

JavaScript客户端存储

2015-07-16 16:57 585 查看
javascript客户端存储localStoragecookiesessionStorage

目录(?)[-]

一localStorage和sessionStorage
二Cookie
三应用程序缓存
四离线Web应用

navigator.online:浏览器是否连接到网络

常见的客户端存储有几种:第一种,Web存储,其中包含localStorage对象和sessionStorage对象;第二种,Cookie,其作为一种被服务端脚本使用的客户端存储机制。

一、localStorage和sessionStorage

1. 二者区别在于存储的有效期和作用域的不同:

localStorage存储的数据时永久性的,作用域是限定在文档源级别的(文档源是通过协议、主机、端口三者确定)。注意其作用域也受到浏览器供应商限制。

sessionStorage作用域也是限定在文档源中,因此非同源文档无法共享sessionStorage,不仅如此,其作用域还被限定在窗口中(顶级窗口)。一个浏览器标签页包含两个iframe是可以共享的。

[javascript]
view plaincopy

localStorage.setItem("x",1); //以“x”的名字存储一个数值
localStorage.getItem("x"); //获取数值

for(var i=0;i<localStorage.length;i++){
var name = localStorage.key(i);
var value = localStorage.getItem(name);
}

localStorage.removeItem("x"); //删除“x”项
localStorage.clear(); //全部删除

//存储对象的处理
var o = {x:1};
var oStr = JSON.stringify(o); //由于存储的内容都是字符串,序列化对象
localStorage.setItem("o",oStr);
localStorage.getItem("o"); //{"x":1} typeof类型:string
JSON.parse(localStorage.getItem("o")).x; //反序列化

// 识别使用哪种存储机制
var memory = window.localStorage || (window.UserDataStorage && new UserDataStorage()) || new CookieStorage();
// 然后在对应机制中获取数据
memory.getItem("name");

2. 存储事件

无论什么时候存储在localStorage和sessionStorage的数据发生改变,浏览器都会在其他对该数据可见的窗口对象上触发存储事件(但是,在对数据进行改变的窗口对象上是不会触发的)。为存储事件注册处理程序可以通过addEventListener()方法(IE下使用addEvent()方法)。监听storage。

[javascript]
view plaincopy

if(window.addEventListener){
window.addEventListener("storage",handle_storage,false);
}else if(window.attachEvent){
window.attachEvent("onstorage",handle_storage);
}


function handle_storage(e){
if(!e){
e=window.event;
}
//showStorage();
}

对于事件变量e,是一个StorageEvent对象,提供了一些实用的属性,可以很好的观察键值对的变化

storageArea: 表示存储类型(Session或Local)

key:发生改变项的key

oldValue: key的原值

newValue:key的新值

url*:key改变发生的URL【使用url属性前,你应该先检查它是否存在,如果没有url属性,则应该使用uri属性】

最后需要注意的是,localStorage和存储事件都是采用广播机制,浏览器会对目前正在访问同样站点的所有窗口发送消息。

二、Cookie

绝大数浏览器可以通过navigator.cookieEnabled这个属性来检测Cookie是否启用!

Cookie的有效期和整个浏览器进程而不是单个浏览器窗口有效期一致。

默认情况下,cookie和创建它的WEB页面有关,并对该WEB页面以及和该WEB页面同目录或者子目录的其他WEB页面可见。

将cookie的路径设置为“/”等于是让cookie和localStorage拥有同样的作用域。

1. 保存cookie

cookie的名/值中的值是不允许包括分号、逗号和空白符,因此,在存储前一般可以采用JavaScript核心的全局函数encodeURIComponent()对值进行编码。

[javascript]
view plaincopy

// 以name/value形式存储cookie
function setCookie(name,value,daysToLive){
var cookie = name + "=" + encodeURIComponent(value);
if(typeof daysToLive === 'number'){
cookie += "; max-age=" + (daysToLive*60*60*24); //分号空格
}
document.cookie = cookie;
}

// 读取全部cookie
function getCookies(){
var cookie = {};
var all = document.cookie;
if(all === ""){
return cookie;
}
var list = all.split("; "); //注意有空格
for(var i=0; i<list.length; i++){
var item = list[i];
var p = item.indexOf("="); //查找第一个“=”符号
var name = item.substring(0,p);
var value = item.substring(p+1);
value = decodeURIComponent(value);
cookie[name] = value;
}
return cookie;
}

// 读取指定名称cookie项
function getCookie(name){
var arr,reg=new RegExp("(^| )"+name+"=([^;]*)(;|$)");
if(arr=document.cookie.match(reg)){
// unescape() 函数可对通过 escape() 编码的字符串进行解码
// ECMAScript v3 已从标准中删除了 unescape() 函数,建议使用 decodeURI() 和 decodeURIComponent()
//return unescape(arr[2]);
return decodeURIComponent(arr[2]);
}else {
return null;
};
} //getCookie

// 删除指定cookie项
function delCookie(name) {
var exp = new Date();
exp.setTime(exp.getTime() - 1); //有效期,为当前时间的前1s
var cval=getCookie(name);
if(cval!=null)
// 把Date对象转换为"格林威治时间 (GMT)"形式的字符串
document.cookie= name + "="+cval+";expires="+exp.toGMTString();
}

// =======测试=========
setCookie('name',"ligang","100000");
setCookie('age',28,"100000");
console.log(getCookies()['name'])
var age = getCookie('age');
console.log(age)
delCookie('age');
console.log(getCookie('age'))

三、应用程序缓存

首先建立一个清单,包含应用程序依赖的所有URL列表;然后,通过在应用程序在主HTML页面的<html>标签中设置manifest属性,指向到该清单文件即可。

[html]
view plaincopy

<!DOCTYPE HTML>
<html manifest="myapp.appcache">
<head></head>
<body></body>
</html>

#清单文件中的首行内容必须以"CACHE MANIFEST"字符串开头

#myapp.appcache 示例:

[html]
view plaincopy

CACHE MANIFEST

# myapp version 1(更新这个数字以便让浏览器重新下载这个文件)

# 直接缓存的文件
CACHE:
../css/*
../js/site/*


# 必须在线访问
NETWORK:
index.do

# 替代方案【从网络中载入videos/路径下文件失败,会采用缓存资源offline_help.html来代替】
FALLBACK:
vidoes/ offline_help.html

注意,浏览器只检查清单文件,而不会去检查缓存的文件是否有更新。

在更新清单文件之后,用户必须载入应用两次才能保证最新的版本生效:第一次是从缓存中载入老版本随后更新缓存;第二次才从缓存中载入新的版本。

浏览器在更新缓存中会触发一些事件,可以根据这些事件来给反馈信息给用户:

[javascript]
view plaincopy

applicationCache.onupdateready = function(){
var reload = confirm("发现新版本,您是否更新?");
if(reload) location.reload();
}

四、离线Web应用

可以使用localStorage来存储应用数据,然后当在线的时候再将数据长传到服务器。

示例:一个简单的记事本程序

note.html:

[html]
view plaincopy

<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>note</title>
<script src="note.js"></script>
<style>
#editor {width: 100%; height: 250px;}
#statusline {width: 100%;}
</style>
</head>
<body>
<div id="toolbar">
<button id="savebutton" onclick="save()">Save</button>
<button onclick="sync();">Sync Note</button>
<button onclick="applicationCache.update();">Update Application</button>
</div>
<textarea id="editor"></textarea>
<div id="statusline"></div>
</body>
</html>

note.js:

[javascript]
view plaincopy

// 全局变量
var editor,statusline,savebutton,idletimer;

window.onload = function(){
//第一次载入时,初始化本地存储
if(localStorage.note == null) localStorage.note = "";
if(localStorage.lastModified == null) localStorage.lastModified = 0;
if(localStorage.lastSaved == null) localStorage.lastSaved =0;

// 查找元素,并初始化全局变量
editor = document.getElementById("editor");
statusline = document.getElementById("statusline");
savebutton = document.getElementById("savebutton");

// 初始化编辑器,将保存的笔记数据填充为其内容
editor.value = localStorage.note;
// 同步前禁止编辑
editor.disabled = true;

// 一旦文本区有内容输入
editor.addEventListener("input", function(e){
// 将新的值保存到localStorage中
localStorage.note = editor.value;
localStorage.lastModified = Date.now();
// 重置闲置计时器
if(idletimer) clearTimeout(idletimer);
idletimer = setTimeout(save, 5000);
// 启用保存按钮
savebutton.disabled = false;
},false);

// 每次载入应用程序时,尝试同步服务器
sync();
};

// 离开页面前保存数据到服务器
window.onbeforeunload = function(){
if(localStorage.lastModified > localStroage.lastModified)
save();
};

// 离线时,通知用户
window.onoffline = function(){
status("Offline");
};

// 再次返回在线状态时,进行同步
window.ononline = function(){
sync();
};


// 当有新版本应用的时候,提醒用户
// 这里我们也可以采用location.reload()方法来强制重新载入应用
window.applicationCache.onupdateready = function(){
status("A new version of this application is available. Reload to run it.");
};

// 当没有新版本的时候也通知用户
window.applicationCache.onnoupdate = function(){
status("You are running the lasted version of the application.");
};

// 用于在状态栏显示状态消息的一个函数
function status(msg){
statusline.innerHTML = msg;
}

// 每当笔记内容更新后,如果用户停止编辑超过5分钟,就会自动将笔记本上传到服务器(在线状态下)
function save(){
if(idletimer) clearTimeout(idletimer);
idletimer = null;
if(navigator.onLine){
var xhr = new XMLHttpRequest();
xhr.open("PUT","http://localhost/sitesettings/getBadgeInfo.pt");
xhr.send(editor.value);
xhr.onload = function(){
localStorage.lastSave = Date.now();
savebutton.disabled = true;
};
}
}

// 如果检查服务器端是否有新版本的笔记
// 如果没有,则将当前版本保存到服务器端
function sync(){
if(navigator.onLine){
var xhr = new XMLHttpRequest();
xhr.open("GET","http://localhost/sitesettings/getBadgeInfo.pt");
xhr.send();
xhr.onload = function(){
var remoteModTime = 0;
if(xhr.status == 200){
var remoteModTime = xhr.getResponseHeader("Last-Modified");
remoteModTime = new Date(remoteModTime).getTime();
}
if(remoteModTime > localStorage.lastModified){
status("Newer note found on server.");
var useit = confirm("There is a newer verion of the note\n"+
"on the server. Click Ok to use that version\n"+
"or click Cancel to continue editing this\n"+
"version and overwrite the server");
var now = Date.now();
if(useit){
editor.value = localStorage.note = xhr.responseText;
localStorage.lastSaved = now;
status("Newest version downloaded");
}else{
status("Ignoring newer version of the note.");
}
localStorage.lastModified = now;
}else{
ststus("You are editing the current version of the note.");
}
if(localStorage.lastModified > localStorage.lastSaved){
save();
}
editor.disabled = false; // 再次启用编辑器
editor.focus(); // 将光标定位到编辑器中
};
}else{
//离线状态下,不能同步
status("Can't sync while offline");
editor.disabled = false;
editor.focus();
}
}

note.appcache:

[html]
view plaincopy

CACHE MANIFEST
#note v1.0

note.html
note.js

NETWORK:
note
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: