HTML5本地存储后备解决方案


119

我正在寻找可以localStorage在不具有本机支持的浏览器上模拟的javascript库和代码。

基本上,我想对我的网站进行编码以localStorage用于存储数据,并且知道它仍然可以在本身不支持它的浏览器上运行。这意味着库将检测是否window.localStorage存在,并在存在时使用它。如果它不存在,那么它将通过在window.localStorage命名空间中创建自己的实现来创建某种本地存储的后备方法。

到目前为止,我已经找到了以下解决方案:

  1. 简单的sessionStorage实现。
  2. 使用cookie的实现(对此想法不满意)。
  3. Dojo的dojox.storage,但这是它自己的事情,不是真正的后备。

我知道Flash和Silverlight也可以用于本地存储,但是在将它们用作标准HTML5 localStorage的后备时并没有发现任何东西。也许Google Gears也具有此功能?

请分享您发现的所有相关库,资源或代码段!我对纯JavaScript或基于jquery的解决方案特别感兴趣,但我猜这不太可能。


sessionStorage和localStorage都是Web存储规范(dev.w3.org/html5/webstorage)的一部分。唯一的区别是浏览器将保留数据多长时间。我想您不会在其中找到一个实现,而在另一个实现中却找不到(但我不确定100%肯定)
rlovtang 2011年

1
值得一提的是,Gears于去年2月正式贬值 -我不会在此之上做任何事情。
josh3736'1

@rlovtang:谢谢,我知道会话存储和本地存储之间的区别。根据24ways.org的文章(有问题的第一个链接,解决方案#1),Chrome仅支持localStorage,不支持sessionStorage。也许情况已不再如此,因为该文章是在不久前写的。
牛头人

@ josh3736:是的,我个人想避免使用cookie和齿轮。我当然不会依赖它构建任何东西,但是如果它是安装它的人的后备存储机制,并且我没有直接对其进行编码,则可以使用它。
牛头人

所以我实际上是错的:)不知道Chrome曾经支持localStorage但不支持sessionStorage。Chrome至少现在同时支持两者。
rlovtang 2011年

Answers:


56

我使用PersistJSgithub存储库),它对您的代码无缝且透明地处理客户端存储。您使用单个API并获得对以下后端的支持:

  • flash:Flash 8持久存储。
  • gears:基于Google Gears的持久性存储。
  • localstorage:HTML5草案存储。
  • whatwg_db:HTML5草案数据库存储。
  • globalstorage:HTML5草案存储(旧规范)。
  • 即:Internet Explorer用户数据行为。
  • cookie:基于cookie的持久性存储。

可以禁用其中任何一个,例如,如果您不想使用cookie。有了这个库,您将在IE 5.5 +,Firefox 2.0 +,Safari 3.1+和Chrome中获得本地客户端存储支持;以及浏览器具有Flash或Gears的插件辅助支持。如果启用cookie,它将在所有功能中起作用(但限于4 kB)。


10
仍然支持PersistJS吗?我想知道它如何解决浏览器升级和所选存储方法更改(例如本地存储可用)的问题。旧位置是否无法访问?
jcalfee314

2
至少看起来好像不再处于主动开发中了。
Mahn 2014年

这是一个非常大胆的图书馆。如果没有关于大多数技术的最大大小的任何知识,我们应该确定我们的应用程序运行得很幸运。如果您要保存<64KB,这似乎只是一个解决方案。
花花公子

@julmot这就是图书馆的目的。在提取繁琐的内容的同时提供便利。有了足够的研究和时间,通常无论最大尺寸如何,您都可以弄清楚如何使其工作。当然,该项目的作者似乎认为这太过分了……
William

您知道这是否适用于Safari私人浏览模式吗?目前,我遇到一个问题,其中Safari Private Browsing macOS和iOS不支持localStorage。
奥斯汀

61

基于纯JS的简单localStorage polyfill:

演示:http//jsfiddle.net/aamir/S4X35/

HTML:

<a href='#' onclick="store.set('foo','bar')">set key: foo, with value: bar</a><br/>
<a href='#' onclick="alert(store.get('foo'))">get key: foo</a><br/>
<a href='#' onclick="store.del('foo')">delete key: foo</a>​

JS:

window.store = {
    localStoreSupport: function() {
        try {
            return 'localStorage' in window && window['localStorage'] !== null;
        } catch (e) {
            return false;
        }
    },
    set: function(name,value,days) {
        if (days) {
            var date = new Date();
            date.setTime(date.getTime()+(days*24*60*60*1000));
            var expires = "; expires="+date.toGMTString();
        }
        else {
            var expires = "";
        }
        if( this.localStoreSupport() ) {
            localStorage.setItem(name, value);
        }
        else {
            document.cookie = name+"="+value+expires+"; path=/";
        }
    },
    get: function(name) {
        if( this.localStoreSupport() ) {
            var ret = localStorage.getItem(name);
            //console.log(typeof ret);
            switch (ret) {
              case 'true': 
                  return true;
              case 'false':
                  return false;
              default:
                  return ret;
            }
        }
        else {
            // cookie fallback
            /*
             * after adding a cookie like
             * >> document.cookie = "bar=test; expires=Thu, 14 Jun 2018 13:05:38 GMT; path=/"
             * the value of document.cookie may look like
             * >> "foo=value; bar=test"
             */
            var nameEQ = name + "=";  // what we are looking for
            var ca = document.cookie.split(';');  // split into separate cookies
            for(var i=0;i < ca.length;i++) {
                var c = ca[i];  // the current cookie
                while (c.charAt(0)==' ') c = c.substring(1,c.length);  // remove leading spaces
                if (c.indexOf(nameEQ) == 0) {  // if it is the searched cookie
                    var ret = c.substring(nameEQ.length,c.length);
                    // making "true" and "false" a boolean again.
                    switch (ret) {
                      case 'true':
                          return true;
                      case 'false':
                          return false;
                      default:
                          return ret;
                    }
                }
            }
            return null; // no cookie found
        }
    },
    del: function(name) {
        if( this.localStoreSupport() ) {
            localStorage.removeItem(name);
        }
        else {
            this.set(name,"",-1);
        }
    }
}​

4
为什么这没有得到认可!?谢啦!
罗伯特

4
:)-我不喜欢为我需要的所有内容添加整个lib。
Aamir Afridi 2013年

2
JavaScript是否允许在var expires本地定义然后在其他范围内定义用户?在功能上set
happy_marmoset13年

3
只是想指出一点,当您允许在cookie上设置过期时间时,localStorage将永远不会过期。如果您正在寻找过期的物品,这可能会导致一些问题。将过期日期添加到本地存储中,然后进行日期比较以查看其是否仍然适用可能是有益的。当然,我也认为如果您需要过期,就应该只使用cookie。但是我认为该脚本要么不允许过期,要么两者都不允许过期,而不是像当前那样前后不一致。
汉娜2014年

1
@MohsinSaeed在私有模式下,我认为浏览器也将不允许您创建cookie。superuser.com/questions/589248/...
阿米尔·阿夫里迪

19

您是否在Modernizr Wiki上看到了polyfill页面?

https://github.com/Modernizr/Modernizr/wiki/HTML5-Cross-browser-Polyfills

在该页面上的“ Webstorage”部分中查找,您将看到10种潜在的解决方案(截至2011年7月)。

祝好运!标记


1
似乎他们都没有在“私人/隐身”模式下工作(例如Safari或Chrome),因为他们的解决方法是创建Cookie,并且在该模式下也将其禁用。
亚历克斯·克劳斯

14

以下是Aamir Afridi响应的整理版本,将其所有代码封装在本地范围内。

我删除了创建全局ret变量的引用,还删除了将存储的“ true”和“ false”字符串解析为BrowserStorage.get()方法中的方法,如果实际上尝试存储字符串“ true”或“假”。

由于本地存储API仅支持字符串值,因此仍然可以通过将JavaScript变量数据编码为JSON字符串来存储/检索JavaScript变量数据及其相应的数据类型,然后可以使用JSON编码/解码库(例如https)对其进行解码: //github.com/douglascrockford/JSON-js

var BrowserStorage = (function() {
    /**
     * Whether the current browser supports local storage as a way of storing data
     * @var {Boolean}
     */
    var _hasLocalStorageSupport = (function() {
        try {
            return 'localStorage' in window && window['localStorage'] !== null;
        } catch (e) {
            return false;
        }
    })();

    /**
     * @param {String} name The name of the property to read from this document's cookies
     * @return {?String} The specified cookie property's value (or null if it has not been set)
     */
    var _readCookie = function(name) {
        var nameEQ = name + "=";
        var ca = document.cookie.split(';');
        for (var i = 0; i < ca.length; i++) {
            var c = ca[i];
            while (c.charAt(0) == ' ') c = c.substring(1, c.length);
            if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length);
        }

        return null;
    };

    /**
     * @param {String} name The name of the property to set by writing to a cookie
     * @param {String} value The value to use when setting the specified property
     * @param {int} [days] The number of days until the storage of this item expires
     */
    var _writeCookie = function(name, value, days) {
        var expiration = (function() {
            if (days) {
                var date = new Date();
                date.setTime(date.getTime() + (days*24*60*60*1000));
                return "; expires=" + date.toGMTString();
            }
            else {
                return "";
            }
        })();

        document.cookie = name + "=" + value + expiration + "; path=/";
    };

    return {
        /**
         * @param {String} name The name of the property to set
         * @param {String} value The value to use when setting the specified property
         * @param {int} [days] The number of days until the storage of this item expires (if storage of the provided item must fallback to using cookies)
         */
        set: function(name, value, days) {
            _hasLocalStorageSupport
                ? localStorage.setItem(name, value)
                : _writeCookie(name, value, days);
        },

        /**
         * @param {String} name The name of the value to retrieve
         * @return {?String} The value of the 
         */
        get: function(name) {
            return _hasLocalStorageSupport
                ? localStorage.getItem(name) 
                : _readCookie(name);
        },

        /**
         * @param {String} name The name of the value to delete/remove from storage
         */
        remove: function(name) {
            _hasLocalStorageSupport
                ? localStorage.removeItem(name)
                : this.set(name, "", -1);
        }
    };
})();

10

我个人更喜欢amplify.js。过去,它对我来说确实非常有效,我建议将其用于所有本地存储需求。

支持IE 5 +,Firefox 2 +,Safari 4 +,Chrome,Opera 10.5 +,iPhone 2 +,Android 2+,并提供一致的API来处理跨浏览器的存储




1

草坪椅似乎也是一个不错的选择

草坪椅有点像沙发,除了较小的和外面的。非常适合需要轻量级,自适应,简单而优雅的持久性解决方案的html5移动应用程序。

  • 集合。草地椅实例实际上只是一系列对象。
  • 适应性持久性。基础存储在一致的接口之后抽象。
  • 可插入的收集行为。有时我们需要收集助手,但并非总是如此。

0

存在realstorage,它使用Gears作为后备。


谢谢。不幸的是,它似乎支持的浏览器少于@ josh3736提出的PersistJS的建议。我仍然会看一下,并赞赏该建议。
牛头人
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.