• web离线应用


      其实浏览器一直都是前端开发人员比较头痛的一个课题,各种兼容性。直到开始规范化和标准化,HTML5的出现。

      在没有这套标准出现之前,对于客户端缓存的问题,我们基本上都是用cookie处理,当然目前除了后台管理类型的软件,面向前端的仍然在沿用cookie,毕竟还有很多老古董还在使用ie和旧的浏览器版本。

      localStorage和sessionStorage这两个全局对象正是新提出的web存储标准。其实这两者都是同一个持久化数组对象,不同的是其存储的有效期和作用于的不同。

                    有效期            访问权限

      localStorage    一直有效,除非主动删除    文档源权限

      sessionStorage    浏览器窗口,标签页      文档源权限,并且是同一个窗口(标签)

      ** 文档源权限,即必须协议(http://),主机名(gabin.top),端口(80)都一致才可共用 

      值得注意的是,这两者都是用字符串索引,也都是用字符串保存数据的。也就是说,如果你用

    localStorage.cache = {one: 1}

      localStorage.cache仍然是“”空字符串,只有通过JSON.parse和JSON.stringify两个方法来进行序列化和反序列化。我们才能正常地去操作。

      这两个对象还提供了比较正式的API

    • setItem(key, value)
    • getItem()  
    • clear()  这个方法必须慎用,将会删除所有的缓存信息,加入存储的数据没有备份的话,将丢失      

      事件:

        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;
        }
  • 相关阅读:
    第08讲树
    第11讲简单算法
    【ZOJ1004】Anagrams by Stack
    【ZOJ1649】Rescue
    第10讲并查集
    网站建设与网页制作课件
    获取鼠标的坐标
    asp.net页面的默认回车事件
    NeatUpload的安装使用
    Page methods 执行顺序
  • 原文地址:https://www.cnblogs.com/gabin/p/5485693.html
Copyright © 2020-2023  润新知