โซลูชันทางเลือกของ HTML5 Local Storage [ปิด]


119

ฉันกำลังมองหาไลบรารี javascript และโค้ดที่สามารถจำลองได้ localStorageบนเบราว์เซอร์ที่ไม่มีการรองรับดั้งเดิม

โดยพื้นฐานแล้วฉันต้องการโค้ดไซต์ของฉันโดยใช้localStorageเพื่อจัดเก็บข้อมูลและรู้ว่าจะยังคงใช้งานได้บนเบราว์เซอร์ที่ไม่รองรับ นี่หมายความว่าไลบรารีจะตรวจพบว่าwindow.localStorageมีอยู่หรือไม่และใช้หากมี หากไม่มีอยู่ก็จะสร้างวิธีการสำรองในพื้นที่จัดเก็บในเครื่องโดยสร้างการใช้งานของตัวเองในwindow.localStorageเนมสเปซ

จนถึงตอนนี้ฉันพบวิธีแก้ปัญหาเหล่านี้แล้ว:

  1. การใช้งานsessionStorageอย่างง่าย
  2. การใช้งานที่ใช้คุกกี้ (ไม่ตื่นเต้นกับแนวคิดนี้)
  3. dojox.storageของ Dojo แต่มันเป็นของของตัวเองไม่ใช่ทางเลือกอื่น

ฉันเข้าใจว่า Flash และ Silverlight สามารถใช้สำหรับพื้นที่จัดเก็บข้อมูลในเครื่องได้เช่นกัน แต่ไม่พบสิ่งใดในการใช้เป็นทางเลือกสำหรับ HTML5 localStorage มาตรฐาน บางที Google Gears ก็มีความสามารถนี้ด้วย?

โปรดแบ่งปันไลบรารีทรัพยากรหรือตัวอย่างโค้ดที่เกี่ยวข้องที่คุณพบ! ฉันสนใจเป็นพิเศษในการแก้ปัญหาที่ใช้ javascript หรือ jquery แต่ฉันเดาว่าไม่น่าเป็นไปได้


sessionStorage และ localStorage เป็นทั้งส่วนหนึ่งของข้อกำหนด Web Storage ( dev.w3.org/html5/webstorage ) ความแตกต่างเพียงอย่างเดียวคือระยะเวลาที่เบราว์เซอร์จะเก็บข้อมูลไว้ ฉันเดาว่าคุณจะไม่พบการใช้งานที่คุณมี แต่ไม่ใช่อย่างอื่น (แต่ฉันไม่แน่ใจ 100%)
rlovtang

1
เป็นมูลค่าการกล่าวขวัญว่า Gears ถูกตัดสิทธิอย่างเป็นทางการเมื่อเดือนกุมภาพันธ์ที่ผ่านมา - ฉันจะไม่สร้างอะไรเลย
josh3736

@rlovtang: ขอบคุณฉันตระหนักถึงความแตกต่างระหว่างเซสชันและที่เก็บข้อมูลในเครื่อง ตามบทความของ 24ways.org (ลิงก์แรกที่เป็นปัญหาโซลูชัน # 1) Chrome สนับสนุนเฉพาะ localStorage ไม่ใช่ sessionStorage บางทีนั่นอาจจะไม่ใช่อีกต่อไปเนื่องจากบทความนั้นเขียนไว้เมื่อไม่นานมานี้
Tauren

@ josh3736: ใช่ฉันต้องการหลีกเลี่ยงการใช้คุกกี้และเกียร์เป็นการส่วนตัว แน่นอนว่าฉันจะไม่สร้างอะไรที่ต้องพึ่งพามัน แต่ถ้ามันเป็นกลไกการจัดเก็บข้อมูลสำรองสำหรับคนที่ติดตั้งไว้และฉันไม่ได้เขียนโค้ดโดยตรงมันก็สามารถใช้ได้
Tauren

ดังนั้นฉันคิดผิดจริงๆ :) ไม่ทราบว่า Chrome เคยรองรับ localStorage แต่ไม่ใช่ sessionStorage Chrome มีการสนับสนุนสำหรับทั้งสองอย่างเป็นอย่างน้อย
rlovtang

คำตอบ:


56

ฉันใช้PersistJS (ที่เก็บ github ) ซึ่งจัดการที่เก็บข้อมูลฝั่งไคลเอ็นต์อย่างราบรื่นและโปร่งใสกับโค้ดของคุณ คุณใช้ API เดียวและรับการสนับสนุนสำหรับแบ็กเอนด์ต่อไปนี้:

  • แฟลช: แฟลช 8 พื้นที่จัดเก็บถาวร
  • เกียร์: พื้นที่เก็บข้อมูลถาวรที่ใช้ Google Gears
  • localstorage: ที่เก็บแบบร่าง HTML5
  • whatwg_db: ที่เก็บฐานข้อมูลแบบร่าง HTML5
  • globalstorage: ที่เก็บแบบร่าง HTML5 (ข้อมูลจำเพาะเก่า)
  • เช่น: พฤติกรรมผู้ใช้ Internet Explorer
  • คุกกี้: การจัดเก็บถาวรที่ใช้คุกกี้

สิ่งเหล่านี้สามารถปิดใช้งานได้เช่นหากคุณไม่ต้องการใช้คุกกี้ ด้วยไลบรารีนี้คุณจะได้รับการสนับสนุนพื้นที่เก็บข้อมูลฝั่งไคลเอ็นต์ใน IE 5.5+, Firefox 2.0+, Safari 3.1+ และ Chrome และการสนับสนุนปลั๊กอินหากเบราว์เซอร์มี Flash หรือ Gears หากคุณเปิดใช้งานคุกกี้คุกกี้จะทำงานได้ทุกอย่าง (แต่จะ จำกัด ไว้ที่ 4 kB)


10
PersistJS ยังรองรับอยู่ไหม ฉันสงสัยว่ามันแก้ปัญหาที่เบราว์เซอร์ได้รับการอัปเกรดและวิธีการจัดเก็บที่เลือกเปลี่ยนไปอย่างไร (บอกว่าที่เก็บข้อมูลในเครื่องพร้อมใช้งาน) สถานที่เก่าไม่สามารถเข้าถึงได้หรือไม่
jcalfee314

2
อย่างน้อยก็ดูเหมือนว่าจะไม่ได้อยู่ในการพัฒนาอีกต่อไป
Mahn

นี่เป็นห้องสมุดที่บ้าระห่ำมาก หากไม่มีความรู้ใด ๆ เกี่ยวกับขนาดสูงสุดในเทคโนโลยีส่วนใหญ่เราควรจะเข้าใจว่าแอปของเราทำงานด้วยความโชคดีมาก ... ดูเหมือนว่านี่จะเป็นเพียงวิธีแก้ปัญหาหากคุณต้องการประหยัด <64KB
เพื่อน

@julmot นั่นคือสิ่งที่ห้องสมุดมีไว้เพื่อ อำนวยความสะดวกในขณะที่แยกสิ่งที่น่าเบื่อออกไป ด้วยการค้นคว้าและเวลาที่เพียงพอโดยปกติคุณจะสามารถหาวิธีทำให้มันได้ผลโดยไม่คำนึงถึงขนาดสูงสุด แน่นอนว่าดูเหมือนผู้เขียนโครงการนั้นจะตัดสินใจว่ามันมากเกินไป ...
วิลเลียม

คุณรู้หรือไม่ว่าสิ่งนี้ใช้ได้กับโหมด Safari Private Browsing หรือไม่? ขณะนี้ฉันมีปัญหาที่ไม่รองรับ localStorage ใน Safari Private Browsing ทั้ง macOS และ iOS
Austin

61

โพลีฟิลล์ localStorage แบบธรรมดาที่ใช้ JS บริสุทธิ์:

การสาธิต: 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
ทำไมถึงไม่ได้รับการยอมรับ!? ขอบคุณ!
Robert

4
:) - ฉันไม่ชอบเพิ่ม lib ทั้งหมดสำหรับทุกสิ่งที่ฉันต้องการ
Aamir Afridi

2
ได้รับอนุญาตใน JavaScript เพื่อกำหนดvar expiresภายในเครื่องแล้วใช้ผู้ใช้ในขอบเขตอื่นหรือไม่? ในฟังก์ชั่นset
happy_marmoset

3
แค่อยากจะชี้ให้เห็นว่าในขณะที่คุณอนุญาตให้ตั้งค่าการหมดอายุบนคุกกี้ localStorage จะไม่มีวันหมดอายุ ซึ่งอาจทำให้เกิดปัญหาบางอย่างหากคุณกำลังมองหาบางอย่างที่หมดอายุ อาจเป็นประโยชน์ที่จะรวมการเพิ่มวันที่หมดอายุในที่เก็บข้อมูลในเครื่องแล้วทำการเปรียบเทียบวันที่เพื่อดูว่ายังใช้ได้หรือไม่ แน่นอนฉันจะเถียงว่าคุณควรใช้คุกกี้หากคุณต้องการวันหมดอายุ แต่ฉันคิดว่าสคริปต์นี้ไม่ควรอนุญาตให้หมดอายุหรืออนุญาตสำหรับทั้งสองอย่างแทนที่จะไม่สอดคล้องกันเหมือนในปัจจุบัน
Hanna

1
@MohsinSaeed ในโหมดส่วนตัวฉันคิดว่าเบราว์เซอร์จะไม่อนุญาตให้คุณสร้างคุกกี้ด้วย superuser.com/questions/589248/…
Aamir Afridi

19

คุณเคยเห็นหน้า polyfill ใน Modernizr wiki หรือไม่?

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

มองหาส่วนการจัดเก็บเว็บในหน้านั้นและคุณจะเห็นโซลูชันที่เป็นไปได้ 10 วิธี (ข้อมูล ณ เดือนกรกฎาคม 2554)

โชคดี! เครื่องหมาย


1
ดูเหมือนว่าไม่มีตัวใดทำงานในโหมดส่วนตัว / ไม่ระบุตัวตน (เช่น Safari หรือ Chrome) เนื่องจากวิธีแก้ปัญหาคือการสร้างคุกกี้ซึ่งถูกปิดใช้งานในโหมดนั้นด้วย
Alex Klaus

14

ด้านล่างนี้เป็นคำตอบของ Aamir Afridi เวอร์ชันที่เป็นระเบียบเรียบร้อยซึ่งจะเก็บโค้ดทั้งหมดไว้ในขอบเขตภายใน

ฉันได้ลบการอ้างอิงที่สร้างretตัวแปรส่วนกลางและยังลบการแยกวิเคราะห์สตริง "จริง" และ "เท็จ" ที่เก็บไว้ออกเป็นค่าบูลีนภายในBrowserStorage.get()เมธอดซึ่งอาจทำให้เกิดปัญหาหากมีผู้พยายามจัดเก็บสตริง "จริง" หรือ "false"

เนื่องจาก API การจัดเก็บในตัวเครื่องรองรับเฉพาะค่าสตริงจึงยังคงสามารถจัดเก็บ / ดึงข้อมูลตัวแปร JavaScript พร้อมกับประเภทข้อมูลที่เหมาะสมได้โดยการเข้ารหัสข้อมูลดังกล่าวเป็นสตริง JSON ซึ่งสามารถถอดรหัสโดยใช้ไลบรารีเข้ารหัส / ถอดรหัส 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 เป็นทางเลือก


ขอบคุณ น่าเสียดายที่ดูเหมือนว่ามันจะรองรับเบราว์เซอร์น้อยกว่าคำแนะนำของ PersistJS ของ @ josh3736 ฉันจะยังคงดูและขอบคุณข้อเสนอแนะ
Tauren
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.