标签:
其实浏览器一直都是前端开发人员比较头痛的一个课题,各种兼容性。直到开始规范化和标准化,HTML5的出现。
在没有这套标准出现之前,对于客户端缓存的问题,我们基本上都是用cookie处理,当然目前除了后台管理类型的软件,面向前端的仍然在沿用cookie,毕竟还有很多老古董还在使用ie和旧的浏览器版本。
localStorage和sessionStorage这两个全局对象正是新提出的web存储标准。其实这两者都是同一个持久化数组对象,不同的是其存储的有效期和作用于的不同。
有效期 访问权限
localStorage 一直有效,除非主动删除 文档源权限
sessionStorage 浏览器窗口,标签页 文档源权限,并且是同一个窗口(标签)
** 文档源权限,即必须协议(http://),主机名(gabin.top),端口(80)都一致才可共用
值得注意的是,这两者都是用字符串索引,也都是用字符串保存数据的。也就是说,如果你用
localStorage.cache = {one: 1}
localStorage.cache仍然是“”空字符串,只有通过JSON.parse和JSON.stringify两个方法来进行序列化和反序列化。我们才能正常地去操作。
这两个对象还提供了比较正式的API
事件:
onstorage:不同窗口层级或者不同窗口(localStorage)中储存数据的时候将会广播。
################################################
下面是应用程序缓存
################################################
applicationCache对象,目前我在最新版IDEA中都无法得到这个全局对象的索引,但是在chrome下,确实是可用的。
不同于前面所讲的web存储,applicationCache更像是一个程序安装包,而非缓存,它并不会随着清除浏览器缓存而被删除。
其实我也是在写这篇随记的前一天才花了几个小时的时间,还熬夜写了个demo。说实话,我也没有那么深的了解。只是项目中需要调研,所以做了下研究。
应用程序缓存基本上由一个清单来构成,它大概是这样的:
CACHE MANIFEST # 通过修改版本号,可以强制更新缓存 # version 1.0.9 # 一进入带有此清单链接的页面,将会开始缓存的内容 # 没有带绝对路径的都是相对于清单文件的相对路径 CACHE: permanote.html /static/jquery/jquery-1.8.0.js permanote.js FALLBACK: # 下方每行都是两个值,以空格隔开,前面的地址将尝试联网获取,取不到的时候将用第二个缓存代替 http://ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js /static/jquery/jquery-1.8.0.js NETWORK: # 下面的地址都将联网获取 /cache/note
文件的头固定以 CACHE MANIFEST开头,一般文件的后缀是 .appcache
CACHE:表示下面的url都将缓存到本地
FALLBACK:表示将先联网获取,如果获取不到用备份的缓存数据代替
NETWORK:表示只能通过联网获取
(* 资料中都有提及需要服务器返回.appcache文件的时候mine-type带有text/cache-manifest,但是目测我都没有用到,以后有遇到这个问题再补上)
现在我们还缺少一个访问页面:
<!DOCTYPE html> <html lang="en" manifest="/static/cache/note/permanote.appcache"> <head> <meta charset="UTF-8"> <title>应用程序缓存示例-记事本</title> <script src="/static/jquery/jquery-1.8.0.js"></script> <script src="permanote.js"></script> <style> #editor { width: 100%; height:250px; } #statusline { width: 100%; } </style> </head> <body> <div id="toolbar"> <button id="saveButton">保存</button> <button id="syncButton">同步笔记本</button> <button id="updateButton">更新离线程序</button> </div> <textarea id="editor"></textarea> <div id="statusline"></div> </body> </html>
permanote.js:
(function($) { var editor, statusline, saveButton, syncButton, updateButton, idleTimer, localStorage = window.localStorage; window.onload = function() { // 第一次初始化时,初始化本地存储 if (localStorage.note == null) { localStorage.note = ""; } if (localStorage.lastModified == null) { localStorage.lastModified = 0; } if (localStorage.lastSaved == null) { localStorage.lastSaved = 0; } editor = $("#editor"); statusline = $("#statusline"); saveButton = $("#saveButton"); syncButton = $("#syncButton"); updateButton = $("#updateButton"); editor.val(localStorage.note); editor.attr("disabled", true); // 同步前禁止编辑 // 一旦文本区域有内容输入 editor.bind("input", function(e) { // 将新的值保存到localStorage中 localStorage.note = editor.val(); localStorage.lastModified = Date.now(); // 重置闲置计时器 if (idleTimer) window.clearTimeout(idleTimer); idleTimer = setTimeout(save, 5000); // 启用保存按钮 saveButton.removeAttr("disabled"); }); saveButton.bind("click", save); syncButton.bind("click", sync); updateButton.bind("click", function() { applicationCache.update(); }); // 每次载入应用程序时,尝试同步服务器 sync(); } // 离开页面前保存数据到服务器 window.onbeforeunload = function() { if (localStorage.lastModified > localStorage.lastSaved) { save(); } } // 离线时,通知用户 window.onoffline = function() { msgStatus("离线"); } // 再次返回在线状态时,进行同步 window.online = function() { sync(); } // 当有新版本的时候通知用户 // 也可以强制重新载入,location.reload(); window.applicationCache.onupdateready = function() { msgStatus("正在更新新版本..."); location.reload(); } // 没有新版本的 时候也通知用户 window.applicationCache.onnoupdate = function() { msgStatus("没有可更新的版本"); } // 每当笔记内容更新后,如果用户停止编辑超过五分钟, // 就会自动将笔记文本上传到服务器(在线状态下) function save() { if (idleTimer) { clearTimeout(idleTimer); } idleTimer = null; if (navigator.onLine) { $.post("/cache/note", {note: editor.val()}, function() { localStorage.lastSaved = Date.now(); saveButton.attr("disabled", true); }); } } // 检查服务器是否有新版本的笔记 // 如果没有,则将当前版本保存到服务器端 function sync() { if (navigator.onLine) { $.get("/cache/note", function(data) { var remoteModTime = 0; remoteModTime = data["last"]; remoteModTime = new Date(remoteModTime).getTime(); if (remoteModTime > localStorage.lastSaved) { msgStatus("发现需要更新的内容"); var useit = confirm("是否使用新版本内容替换当前数据") var now = Date.now(); if (useit) { localStorage.note = data.data; editor.val(data.data); localStorage.lastSaved = now; msgStatus("已经下载了最新数据"); } } else { msgStatus("没有发现新数据"); } if (localStorage.lastModified > localStorage.lastSaved) { save(); } editor.removeAttr("disabled"); // 再次启用编辑器 editor.focus(); }); } else { // 离线状态,不能同步 msgStatus("离线状态,同步失败"); editor.removeAttr("disabled"); // 再次启用编辑器 editor.focus(); } } function msgStatus(status) { statusline.text(status); } } (jQuery));
访问的结果是这样的:
服务器的代码大概是这样:
private static String note = ""; private static Date lastModify; @RequestMapping(value = "/note", method = RequestMethod.POST) @ResponseBody public Map<String, Object> note(String note) { this.note = note; if (note != this.note) { lastModify = new Date(); } Map<String, Object> successMap = RenderUtils.getSuccessMap(); successMap.put("data", note); return successMap; } @RequestMapping(value = "/note", method = RequestMethod.GET) @ResponseBody public Map<String, Object> note() { Map<String, Object> successMap = RenderUtils.getSuccessMap(); successMap.put("data", note); successMap.put("last", lastModify); return successMap; }
标签:
原文地址:http://www.cnblogs.com/gabin/p/5485693.html