Nesneleri HTML5'te depolama localStorage


2511

Bir JavaScript nesnesini HTML5'te depolamak istiyorum localStorage, ancak nesnem görünüşte bir dizeye dönüştürülüyor.

İlkel JavaScript türlerini ve dizilerini kullanarak saklayabilir ve alabilirim localStorage, ancak nesneler işe yaramıyor. Yapmalılar mı?

İşte benim kod:

var testObject = { 'one': 1, 'two': 2, 'three': 3 };
console.log('typeof testObject: ' + typeof testObject);
console.log('testObject properties:');
for (var prop in testObject) {
    console.log('  ' + prop + ': ' + testObject[prop]);
}

// Put the object into storage
localStorage.setItem('testObject', testObject);

// Retrieve the object from storage
var retrievedObject = localStorage.getItem('testObject');

console.log('typeof retrievedObject: ' + typeof retrievedObject);
console.log('Value of retrievedObject: ' + retrievedObject);

Konsol çıkışı

typeof testObject: object
testObject properties:
  one: 1
  two: 2
  three: 3
typeof retrievedObject: string
Value of retrievedObject: [object Object]

Bana setItemyöntem, girdiyi saklamadan önce bir dizeye dönüştürüyor gibi görünüyor .

Safari, Chrome ve Firefox'ta bu davranışı görüyorum, bu yüzden tarayıcıya özgü bir hata veya sınırlama değil , HTML5 Web Depolama spesifikasyonunu yanlış anladığımı varsayıyorum .

Http://www.w3.org/TR/html5/infrastructure.html'de açıklanan yapılandırılmış klon algoritmasını anlamaya çalıştım . Ne dediğini tam olarak anlamıyorum, ama belki de benim sorunum nesnemin özellikleri numaralandırılamaz olmakla ilgili (???)

Kolay bir çözüm var mı?


Güncelleme: W3C nihayetinde yapılandırılmış klon spesifikasyonu hakkındaki fikirlerini değiştirdi ve spesifikasyonu uygulamalara uyacak şekilde değiştirmeye karar verdi. Bkz. Https://www.w3.org/Bugs/Public/show_bug.cgi?id=12111 . Dolayısıyla bu soru artık% 100 geçerli değil, ancak cevaplar hala ilgi çekici olabilir.


17
BTW, "yapılandırılmış klon algoritması" okumanız doğru, sadece uygulamalar sadece dize değerlerinden uygulamalar çıktıktan sonra buna değiştirildi. Bu sorunu izlemek için bugzilla.mozilla.org/show_bug.cgi?id=538142 mozilla ile hata bildirdim .
Nickolay

2
Bu indexedDB için bir iş gibi görünüyor ...
markasoftware

1
LocalStorage'da bir Nesne dizisini saklamaya ne dersiniz? Ben dize dönüştürülüyor aynı sorunla karşı karşıya.
Jayant Pareek

1
bunun yerine diziyi serileştirebilir misiniz? JSON ile mağaza gibi stringify sonra yükleme üzerine tekrar ayrıştırmak?
Mart'ta Brandito

1
Javascript veri türlerini (Dizi, Boole, Tarih, Kayan Nokta , Tamsayı, Dize ve Nesne) şeffaf bir şekilde depolamak için localDataStorage'ı kullanabilirsiniz
Mac

Yanıtlar:


3170

Apple , Mozilla ve Mozilla belgelerine tekrar baktığımızda , işlevsellik yalnızca string anahtar / değer çiftlerini işlemek için sınırlı görünmektedir.

Geçici çözüm, nesnenizi saklamadan önce dizgi yapmak ve daha sonra geri getirdiğinizde ayrıştırmak olabilir:

var testObject = { 'one': 1, 'two': 2, 'three': 3 };

// Put the object into storage
localStorage.setItem('testObject', JSON.stringify(testObject));

// Retrieve the object from storage
var retrievedObject = localStorage.getItem('testObject');

console.log('retrievedObject: ', JSON.parse(retrievedObject));

159
meta verilerin kaldırılacağını gözlemleyin. yalnızca anahtar / değer çiftlerine sahip bir nesne alırsınız, bu nedenle davranışa sahip herhangi bir nesnenin yeniden oluşturulması gerekir.
oligofren

5
@CMS, veriler kapasiteyi aşarsa öğe istisna atabilir mi?
Ashish Negi

3
... yalnızca dairesel referansları olan nesnelere uygulanır JSON.stringify(), başvurulan nesneyi, dizgi yaptığımız nesnede tam "içeriğine (dolaylı olarak dizgi) genişletir. Bkz. Stackoverflow.com/a/12659424/2044940
CodeManX

3
Büyük dizileri veya nesneleri ele almanız gerekiyorsa, bu yaklaşımdaki sorun performans sorunlarıdır.
Mark

3
@oligofren true, ama maja doğru olarak eval () => önerdiği gibi , bu iyi bir kullanım, kolayca fonksiyon kodu alabilirsiniz => dize olarak saklayın ve sonra eval () geri :)
jave.web

621

Bir varyantta küçük bir gelişme :

Storage.prototype.setObject = function(key, value) {
    this.setItem(key, JSON.stringify(value));
}

Storage.prototype.getObject = function(key) {
    var value = this.getItem(key);
    return value && JSON.parse(value);
}

Çünkü kısa devre değerlendirme , getObject()edecek hemen geri nulleğer keydepolama değildir. Ayrıca atmaz SyntaxErrorise istisna valueolduğunu ""(boş dize; JSON.parse()o işleyemez).


48
Kullanımı hemen benim için net olmadığı için hızlı bir şekilde eklemek istiyorum: var userObject = { userId: 24, name: 'Jack Bauer' }; Ve ayarlamak için localStorage.setObject('user', userObject); Sonra depodan geri alın userObject = localStorage.getObject('user'); İsterseniz bir dizi nesneyi bile saklayabilirsiniz.
zuallauz

8
Sadece boole ifadesidir. İkinci kısım sadece sol taraf doğruysa değerlendirilir. Bu durumda tüm ifadenin sonucu sağ taraftan olacaktır. Boole ifadelerinin nasıl değerlendirildiğine dayanan popüler bir tekniktir.
Guria

4
Burada yerel değişkenin amacını ve kısayol değerlendirmesini görmüyorum (küçük performans iyileştirmeleri bir yana). Eğer keyYerel Depolama değil, window.localStorage.getItem(key)döner null- bu mu değil bir "geçersiz erişim" istisna - ve JSON.parse(null)iadeler nullsıra - bu mu değil ya bir istisna, Chromium 21 ne de başına ne 5.1 bölümünde 15.12.2 ES , çünkü String(null) === "null"hangi kutu JSON hazır bilgisi olarak yorumlanabilir .
PointedEars

6
Yerel Depolama'daki değerler her zaman ilkel dize değerleridir. Yani bu kısayol değerlendirmesinin ele aldığı şey, daha önce birinin ""(boş dize) depolanmış olmasıdır . Çünkü tip-dönüştürür falseve JSON.parse("")bir SyntaxErroristisna atacak , çağrılmaz.
PointedEars

2
Bu IE8'de çalışmaz, bu yüzden desteklemeniz gerekiyorsa onaylanmış cevaptaki işlevleri kullanmanız daha iyi olur.
Ezeke

220

Storage nesnesini şu kullanışlı yöntemlerle genişletmeyi yararlı bulabilirsiniz:

Storage.prototype.setObject = function(key, value) {
    this.setItem(key, JSON.stringify(value));
}

Storage.prototype.getObject = function(key) {
    return JSON.parse(this.getItem(key));
}

Bu şekilde, API'nın altında yalnızca dizeleri desteklese bile, gerçekten istediğiniz işlevselliği elde edersiniz.


13
CMS'nin bir fonksiyona yaklaşması iyi bir fikirdir, sadece bir özellik testine ihtiyaç duyar: Biri JSON.stringify için, biri JSON.parse için ve diğeri localStorage'ın aslında bir nesneyi ayarlayıp alıp alamayacağını test etmek için. Ana bilgisayar nesnelerini değiştirmek iyi bir fikir değildir; Bunu ayrı bir yöntem olarak görmeyi tercih ederim localStorage.setObject.
Garrett

4
Bu getObject()bir atacağım SyntaxErrorsaklanan değer ise istisna "", çünkü JSON.parse()kutu olduğunu işlemez. Ayrıntılar için Guria'nın cevabında yaptığım düzenlemeye bakın.
PointedEars

9
Sadece iki sentim, ancak satıcının bu şekilde sağladığı nesneleri genişletmenin iyi bir fikir olmadığından eminim.
Sethen


73

Storage nesnesini genişletmek harika bir çözümdür. API'm için, localStorage için bir cephe oluşturdum ve sonra ayar ve alma sırasında bunun bir nesne olup olmadığını kontrol ettim.

var data = {
  set: function(key, value) {
    if (!key || !value) {return;}

    if (typeof value === "object") {
      value = JSON.stringify(value);
    }
    localStorage.setItem(key, value);
  },
  get: function(key) {
    var value = localStorage.getItem(key);

    if (!value) {return;}

    // assume it is an object that has been stringified
    if (value[0] === "{") {
      value = JSON.parse(value);
    }

    return value;
  }
}

1
Bu neredeyse tam olarak ihtiyacım olan şeydi. Yorumdan önce {value == null) {return false} değerini eklemek zorunda kaldım, aksi takdirde localStorage'da bir anahtarın varlığını kontrol ederken hatayla sonuçlandı.
Francesco Frapporti

2
Aslında bu oldukça havalı. @FrancescoFrapporti ile aynı fikirde olursanız, null değerler için bir if gerekir. Ayrıca bir '|| değer [0] == "[" 'orada bir dizide olup olmadığını test eder.
rob_james

İyi bir nokta, bunu düzenleyeceğim. Null kısma ihtiyacınız olmasa da, bunu yaparsanız üç === öneririm. JSHint veya JSLint kullanırsanız, == kullanmaya karşı uyarılırsınız.
Alex Grande

3
Ve ninja olmayanlar için (benim gibi), birisi bu cevap için bir kullanım örneği verebilir mi? Öyle mi data.set('username': 'ifedi', 'fullname': { firstname: 'Ifedi', lastname: 'Okonkwo'});?
Ifedi Okonkwo

Evet kesinlikle! Kaşıkla beslenme arzumun üstesinden geldiğimde, test etmek için kodu aldım ve anladım. Bu cevabın harika olduğunu düşünüyorum çünkü 1) Kabul edilen cevabın aksine, dize verileri üzerinde belirli kontroller yapmak zaman alır ve 2) Bir sonrakinden farklı olarak, yerel bir nesneyi genişletmez.
Ifedi Okonkwo

64

Stringify tüm sorunları çözmez

Buradaki cevaplar JavaScript'te mümkün olan tüm türleri kapsamıyor gibi görünüyor, bu yüzden onlarla doğru bir şekilde nasıl başa çıkılacağıyla ilgili bazı kısa örnekler:

//Objects and Arrays:
    var obj = {key: "value"};
    localStorage.object = JSON.stringify(obj);  //Will ignore private members
    obj = JSON.parse(localStorage.object);
//Boolean:
    var bool = false;
    localStorage.bool = bool;
    bool = (localStorage.bool === "true");
//Numbers:
    var num = 42;
    localStorage.num = num;
    num = +localStorage.num;    //short for "num = parseFloat(localStorage.num);"
//Dates:
    var date = Date.now();
    localStorage.date = date;
    date = new Date(parseInt(localStorage.date));
//Regular expressions:
    var regex = /^No\.[\d]*$/i;     //usage example: "No.42".match(regex);
    localStorage.regex = regex;
    var components = localStorage.regex.match("^/(.*)/([a-z]*)$");
    regex = new RegExp(components[1], components[2]);
//Functions (not recommended):
    function func(){}
    localStorage.func = func;
    eval( localStorage.func );      //recreates the function with the name "func"

İşlevlerin saklanmasını önermiyorum çünkü eval()kötülük güvenlik, optimizasyon ve hata ayıklama ile ilgili sorunlara yol açabilir. Genel olarak, eval()asla JavaScript kodunda kullanılmamalıdır.

Özel üyeler

JSON.stringify()Nesneleri saklamak için kullanmayla ilgili problem , bu fonksiyonun özel üyeleri serileştirememesidir. Bu sorun, .toString()yöntemin üzerine yazılarak çözülebilir (web depolama alanında veri saklanırken örtük olarak çağrılır):

//Object with private and public members:
    function MyClass(privateContent, publicContent){
        var privateMember = privateContent || "defaultPrivateValue";
        this.publicMember = publicContent  || "defaultPublicValue";

        this.toString = function(){
            return '{"private": "' + privateMember + '", "public": "' + this.publicMember + '"}';
        };
    }
    MyClass.fromString = function(serialisedString){
        var properties = JSON.parse(serialisedString || "{}");
        return new MyClass( properties.private, properties.public );
    };
//Storing:
    var obj = new MyClass("invisible", "visible");
    localStorage.object = obj;
//Loading:
    obj = MyClass.fromString(localStorage.object);

Dairesel referanslar

Ele stringifyalınamayan başka bir sorun da dairesel referanslardır:

var obj = {};
obj["circular"] = obj;
localStorage.object = JSON.stringify(obj);  //Fails

Bu örnekte, JSON.stringify()bir atacağım TypeError "JSON dönüştürülüyor dairesel yapı" . Dairesel referansların saklanması destekleniyorsa, ikinci parametresi JSON.stringify()kullanılabilir:

var obj = {id: 1, sub: {}};
obj.sub["circular"] = obj;
localStorage.object = JSON.stringify( obj, function( key, value) {
    if( key == 'circular') {
        return "$ref"+value.id+"$";
    } else {
        return value;
    }
});

Bununla birlikte, dairesel referansları saklamak için etkili bir çözüm bulmak büyük ölçüde çözülmesi gereken görevlere bağlıdır ve bu tür verilerin geri yüklenmesi de önemsiz değildir.

SO bu sorunla ilgili bazı soru var: Dairesel başvuru ile bir JavaScript nesnesi Stringify (JSON dönüştürmek)


2
Bu nedenle ve söylemeye gerek yok - verilerin Depolama alanına depolanması , basit verilerin kopyalarının tek öncülüne dayanmalıdır . Canlı Nesneler değil.
Roko C. Buljan

51

Birçok çözümü saran harika bir kütüphane var, bu yüzden jStorage adı verilen eski tarayıcıları bile destekliyor

Bir nesne ayarlayabilirsiniz

$.jStorage.set(key, value)

Ve kolayca alın

value = $.jStorage.get(key)
value = $.jStorage.get(key, "default value")

2
@SuperUberDuper jStorage Prototype, MooTools veya jQuery gerektirir
JProgrammer

28

Teorik olarak, fonksiyonları olan nesneleri depolamak mümkündür:

function store (a)
{
  var c = {f: {}, d: {}};
  for (var k in a)
  {
    if (a.hasOwnProperty(k) && typeof a[k] === 'function')
    {
      c.f[k] = encodeURIComponent(a[k]);
    }
  }

  c.d = a;
  var data = JSON.stringify(c);
  window.localStorage.setItem('CODE', data);
}

function restore ()
{
  var data = window.localStorage.getItem('CODE');
  data = JSON.parse(data);
  var b = data.d;

  for (var k in data.f)
  {
    if (data.f.hasOwnProperty(k))
    {
      b[k] = eval("(" + decodeURIComponent(data.f[k]) + ")");
    }
  }

  return b;
}

Ancak, Fonksiyon seri / seri kaldırma güvenilmez o uygulama bağlıdır .


1
İşlev serileştirme / serileştirme , uygulamaya bağlı olduğu için güvenilir değildir . Ayrıca, değiştirmek istediğiniz c.f[k] = escape(a[k]); Unicode kasa ile c.f[k] = encodeURIComponent(a[k]);ve eval('b.' + k + ' = ' + unescape(data.f[k]));ile b[k] = eval("(" + decodeURIComponent(data.f[k]) + ")");. Parantezler gereklidir, çünkü işleviniz doğru şekilde serileştirilmişse, anonim olabilir, ki bu geçerli değildir / böyle bir durum geçersizdir / Statement / (so eval()) SyntaxErroraksi halde istisna oluşturur).
PointedEars

Ve typeofbir operatör , sanki bir işlevmiş gibi yazmayın. Değiştir typeof(a[k])ile typeof a[k].
PointedEars

Önerilerimi uygulamaya ve yaklaşımın güvenilmezliğine vurgu yapmanın yanı sıra aşağıdaki hataları da düzelttim: 1. Tüm değişkenler beyan edilmedi. 2. for- inkendi özellikleri için filtrelenmemiştir. 3. Kaynak gösterme dahil kod stili tutarsızdı.
PointedEars

@PointedEars bu hangi pratik farkı yaratıyor? spesifikasyonda the use and placement of white space, line terminators, and semicolons within the representation String is implementation-dependent. herhangi bir fonksiyonel farklılık görmediğimi söylüyor
Michael

@Michael Alıntı yaptığınız bölüm başlar Note *in particular* that …. Ancak, dönüş değeri belirtimi ile başlar An implementation-dependent representation of the function is returned. This representation has the syntax of a FunctionDeclaration.. Dönüş değeri function foo () {}- uygun bir uygulama olduğu varsayılabilir .
PointedEars

22

Bunun bir kopyası olarak kapatılmış başka bir gönderiye isabet ettikten sonra bu mesaja geldim - 'localstorage'da bir dizi nasıl saklanır?' Her iki iş parçacığının içerdiği bilgilere dayanarak bir çözüm oluşturmayı başardığım için ne iş parçacığı aslında nasıl localStorage bir dizi korumak için tam bir cevap sağlar dışında iyidir.

Bu nedenle, bir dizi içindeki öğeleri itmek / pop / shift yapmak isteyen varsa ve bu dizinin localStorage veya gerçekten sessionStorage'da depolanmasını istiyorlarsa, işte gidiyorsunuz:

Storage.prototype.getArray = function(arrayName) {
  var thisArray = [];
  var fetchArrayObject = this.getItem(arrayName);
  if (typeof fetchArrayObject !== 'undefined') {
    if (fetchArrayObject !== null) { thisArray = JSON.parse(fetchArrayObject); }
  }
  return thisArray;
}

Storage.prototype.pushArrayItem = function(arrayName,arrayItem) {
  var existingArray = this.getArray(arrayName);
  existingArray.push(arrayItem);
  this.setItem(arrayName,JSON.stringify(existingArray));
}

Storage.prototype.popArrayItem = function(arrayName) {
  var arrayItem = {};
  var existingArray = this.getArray(arrayName);
  if (existingArray.length > 0) {
    arrayItem = existingArray.pop();
    this.setItem(arrayName,JSON.stringify(existingArray));
  }
  return arrayItem;
}

Storage.prototype.shiftArrayItem = function(arrayName) {
  var arrayItem = {};
  var existingArray = this.getArray(arrayName);
  if (existingArray.length > 0) {
    arrayItem = existingArray.shift();
    this.setItem(arrayName,JSON.stringify(existingArray));
  }
  return arrayItem;
}

Storage.prototype.unshiftArrayItem = function(arrayName,arrayItem) {
  var existingArray = this.getArray(arrayName);
  existingArray.unshift(arrayItem);
  this.setItem(arrayName,JSON.stringify(existingArray));
}

Storage.prototype.deleteArray = function(arrayName) {
  this.removeItem(arrayName);
}

örnek kullanım - basit dizeleri localStorage dizisine kaydetme:

localStorage.pushArrayItem('myArray','item one');
localStorage.pushArrayItem('myArray','item two');

örnek kullanım - sessionStorage dizisindeki nesneleri saklama:

var item1 = {}; item1.name = 'fred'; item1.age = 48;
sessionStorage.pushArrayItem('myArray',item1);

var item2 = {}; item2.name = 'dave'; item2.age = 22;
sessionStorage.pushArrayItem('myArray',item2);

dizileri işlemek için yaygın yöntemler:

.pushArrayItem(arrayName,arrayItem); -> adds an element onto end of named array
.unshiftArrayItem(arrayName,arrayItem); -> adds an element onto front of named array
.popArrayItem(arrayName); -> removes & returns last array element
.shiftArrayItem(arrayName); -> removes & returns first array element
.getArray(arrayName); -> returns entire array
.deleteArray(arrayName); -> removes entire array from storage

Bu, localStorage veya sessionStorage'da depolanan dizileri işlemek için çok kullanışlı bir yöntem kümesidir ve çekilenden çok daha fazla krediyi hak eder. @Andy Lorenz Paylaşmaya zaman ayırdığınız için teşekkür ederiz!
Velojet



6

LocalDataStorage'ı kullanabilirsinizJavascript veri türlerini (Dizi, Boole, Tarih, , Tamsayı, Dize ve Nesne) şeffaf bir şekilde saklamak . Ayrıca, hafif veri gizleme sağlar, dizeleri otomatik olarak sıkıştırır, anahtar (ad) ile sorguyu ve ayrıca (anahtar) değerine göre sorguyu kolaylaştırır ve anahtarları önek olarak aynı etki alanı içinde bölümlere ayrılmış paylaşılan depolamanın uygulanmasına yardımcı olur.

[YASAL UYARI] Ben yardımcı programın yazarı benim [/ YASAL UYARI]

Örnekler:

localDataStorage.set( 'key1', 'Belgian' )
localDataStorage.set( 'key2', 1200.0047 )
localDataStorage.set( 'key3', true )
localDataStorage.set( 'key4', { 'RSK' : [1,'3',5,'7',9] } )
localDataStorage.set( 'key5', null )

localDataStorage.get( 'key1' )   -->   'Belgian'
localDataStorage.get( 'key2' )   -->   1200.0047
localDataStorage.get( 'key3' )   -->   true
localDataStorage.get( 'key4' )   -->   Object {RSK: Array(5)}
localDataStorage.get( 'key5' )   -->   null

Gördüğünüz gibi, ilkel değerlere saygı duyulur.


1
Bu mükemmel bir kaynak ve tam ihtiyacım olan şey. AngularJS ile iyonik uygulamalar yapıyorum ve localStorage'da bazı javascript nesnelerini kaydetmem gerekiyor ve bu noktaya kadar sadece JSON.parse ve JSON.stringify yapıyorum ve çalışıyorlar, ancak mümkün olmaktan biraz daha hantal sadece böyle bir yardımcı programı kullanmak için. Ben deneyeceğim.
Nmuta

4

Başka bir seçenek de mevcut bir eklentiyi kullanmak olacaktır.

Örneğin persisto , localStorage / sessionStorage için kolay bir arayüz sağlayan ve form alanları (giriş, radyo düğmeleri ve onay kutuları) için kalıcılığı otomatikleştiren açık kaynaklı bir projedir.

persisto özellikleri

(Feragatname: Ben yazarım.)


Hala benim Benioku'da üzerinde çalışıyor, ama benim sürüm değil gerektiren bu persisto yapar göründüğü gibi, jQuery, ancak jQuery eleman Nesneleri başa çıkmak için bir alternatif sağlar yapar. Yakın gelecekte, farklı jQuery Nesneleriyle daha fazla başa çıkmasına ve kalıcı veri gibi şeyleri korumasına yardımcı olmak için daha fazla çalışacağım gibi daha fazlasını ekleyeceğim. Ayrıca, daha basit bir çözüm sağlamaya çalıştığınız için +1! Ayrıca, tüm geleneksel yöntemleri kullanır localStroage; exp: var lsh = new localStorageHelper(); lsh.setItem('bob', 'bill'); Ayrıca etkinlikleri içerir.
SpYk3HH

4

Nesneleri dize olarak saklamak için ejson'u kullanabilirsiniz .

EJSON, daha fazla türü desteklemek için JSON'un bir uzantısıdır. Tüm JSON güvenli türleri ve ayrıca şunları destekler:

Tüm EJSON serileştirmeleri de geçerli JSON'dur. Örneğin, tarihi ve ikili arabelleği olan bir nesne EJSON'da şu şekilde serileştirilir:

{
  "d": {"$date": 1358205756553},
  "b": {"$binary": "c3VyZS4="}
}

İşte ejson kullanarak localStorage sarmalayıcı

https://github.com/UziTech/storage.js

Paketleyicime düzenli ifadeler ve işlevler dahil olmak üzere bazı türler ekledim


2

Ben olması gerektiği gibi kullanmak için sadece 20 satır kod ile başka bir minimalist sarmalayıcı yaptım:

localStorage.set('myKey',{a:[1,2,5], b: 'ok'});
localStorage.has('myKey');   // --> true
localStorage.get('myKey');   // --> {a:[1,2,5], b: 'ok'}
localStorage.keys();         // --> ['myKey']
localStorage.remove('myKey');

https://github.com/zevero/simpleWebstorage


2

Yazılan özellikleri ayarlamak ve almak isteyen daktilo kullanıcıları için:

/**
 * Silly wrapper to be able to type the storage keys
 */
export class TypedStorage<T> {

    public removeItem(key: keyof T): void {
        localStorage.removeItem(key);
    }

    public getItem<K extends keyof T>(key: K): T[K] | null {
        const data: string | null =  localStorage.getItem(key);
        return JSON.parse(data);
    }

    public setItem<K extends keyof T>(key: K, value: T[K]): void {
        const data: string = JSON.stringify(value);
        localStorage.setItem(key, data);
    }
}

Örnek kullanım :

// write an interface for the storage
interface MyStore {
   age: number,
   name: string,
   address: {city:string}
}

const storage: TypedStorage<MyStore> = new TypedStorage<MyStore>();

storage.setItem("wrong key", ""); // error unknown key
storage.setItem("age", "hello"); // error, age should be number
storage.setItem("address", {city:"Here"}); // ok

const address: {city:string} = storage.getItem("address");

2

https://github.com/adrianmay/rhaboo böyle bir şey yazmanıza izin veren yerel bir Depolama şeker katmanıdır:

var store = Rhaboo.persistent('Some name');
store.write('count', store.count ? store.count+1 : 1);
store.write('somethingfancy', {
  one: ['man', 'went'],
  2: 'mow',
  went: [  2, { mow: ['a', 'meadow' ] }, {}  ]
});
store.somethingfancy.went[1].mow.write(1, 'lawn');

JSON.stringify / ayrıştırma kullanmaz, çünkü bu büyük nesnelerde yanlış ve yavaş olacaktır. Bunun yerine, her bir terminal değerinin kendi localStorage girişi vardır.

Muhtemelen rhaboo ile bir ilgim olabileceğini tahmin edebilirsiniz.


1

@Danott tarafından yayınlanan kodun bazı genişletilmiş sürümü

Ayrıca localstorage'dan silme değeri uygular ve yerine Getter ve Setter katmanlarının nasıl ekleneceğini gösterir.

localstorage.setItem(preview, true)

Yazabilirsin

config.preview = true

Tamam işte burada:

var PT=Storage.prototype

if (typeof PT._setItem >='u') PT._setItem = PT.setItem;
PT.setItem = function(key, value)
{
  if (typeof value >='u')//..ndefined
    this.removeItem(key)
  else
    this._setItem(key, JSON.stringify(value));
}

if (typeof PT._getItem >='u') PT._getItem = PT.getItem;
PT.getItem = function(key)
{  
  var ItemData = this._getItem(key)
  try
  {
    return JSON.parse(ItemData);
  }
  catch(e)
  {
    return ItemData;
  }
}

// Aliases for localStorage.set/getItem 
get =   localStorage.getItem.bind(localStorage)
set =   localStorage.setItem.bind(localStorage)

// Create ConfigWrapperObject
var config = {}

// Helper to create getter & setter
function configCreate(PropToAdd){
    Object.defineProperty( config, PropToAdd, {
      get: function ()      { return (  get(PropToAdd)      ) },
      set: function (val)   {           set(PropToAdd,  val ) }
    })
}
//------------------------------

// Usage Part
// Create properties
configCreate('preview')
configCreate('notification')
//...

// Config Data transfer
//set
config.preview = true

//get
config.preview

// delete
config.preview = undefined

Peki, takma ad bölümünü kesebilirsiniz .bind(...). Bununla birlikte, bunu bilmek gerçekten iyi olduğu için koydum. Basit bir şeyin neden get = localStorage.getItem;işe yaramadığını öğrenmek için saatlerimi aldım


1

Varolan Depolama nesnelerini bozmayan, ancak istediğiniz şeyi yapabilmeniz için bir sarıcı oluşturur. Sonuç, herhangi bir nesne gibi erişimi olan normal bir nesnedir, yöntem yoktur.

Yaptığım şey.

1 localStoragemülkün sihir olmasını istiyorsanız :

var prop = ObjectStorage(localStorage, 'prop');

Birden fazlasına ihtiyacınız varsa:

var storage = ObjectStorage(localStorage, ['prop', 'more', 'props']);

Eğer yapmak her şey propya nesneler içeride storage otomatik olarak kaydedilecektir localStorage. Her zaman gerçek bir nesneyle oynuyorsunuz, böylece böyle şeyler yapabilirsiniz:

storage.data.list.push('more data');
storage.another.list.splice(1, 2, {another: 'object'});

Ve izlenen bir nesnenin içindeki her yeni nesne otomatik olarak izlenir.

Çok büyük dezavantajı: o bağlıdır Object.observe()çok sınırlı tarayıcı desteğine sahip böylece. Ve yakında Firefox veya Edge için gelecek gibi görünmüyor.


1

Anahtar değerini Dize Biçimi olmadan depolayamazsınız .

LocalStorage yalnızca anahtar / değer için Dize biçimini destekler.

Bu nedenle, verilerinizi Dizi veya Nesne ne olursa olsun dizeye dönüştürmelisiniz .

Verileri localStorage'da depolamak için öncelikle JSON.stringify () yöntemini kullanarak onu dizgi haline getirin .

var myObj = [{name:"test", time:"Date 2017-02-03T08:38:04.449Z"}];
localStorage.setItem('item', JSON.stringify(myObj));

Daha sonra veri almak istediğinizde, String'i Object'e tekrar ayrıştırmanız gerekir.

var getObj = JSON.parse(localStorage.getItem('item'));

Umarım yardımcı olur.


0

Bir nesneyi saklamak için, bir nesneyi bir dizeden bir nesneye almak için kullanabileceğiniz bir harf oluşturabilirsiniz (anlamlı olmayabilir). Örneğin

var obj = {a: "lol", b: "A", c: "hello world"};
function saveObj (key){
    var j = "";
    for(var i in obj){
        j += (i+"|"+obj[i]+"~");
    }
    localStorage.setItem(key, j);
} // Saving Method
function getObj (key){
    var j = {};
    var k = localStorage.getItem(key).split("~");
    for(var l in k){
        var m = k[l].split("|");
        j[m[0]] = m[1];
    }
    return j;
}
saveObj("obj"); // undefined
getObj("obj"); // {a: "lol", b: "A", c: "hello world"}

Nesneyi bölmek için kullandığınız harfi kullanırsanız bu teknik bazı aksaklıklara neden olur ve aynı zamanda çok deneyseldir.


0

Döngüsel referansları olan nesnelerle çalışmasını sağlamanın bir yolunu buldum.

Döngüsel referansları olan bir nesne yapalım.

obj = {
    L: {
        L: { v: 'lorem' },
        R: { v: 'ipsum' }
    },
    R: {
        L: { v: 'dolor' },
        R: {
            L: { v: 'sit' },
            R: { v: 'amet' }
        }
    }
}
obj.R.L.uncle = obj.L;
obj.R.R.uncle = obj.L;
obj.R.R.L.uncle = obj.R.L;
obj.R.R.R.uncle = obj.R.L;
obj.L.L.uncle = obj.R;
obj.L.R.uncle = obj.R;

JSON.stringifyDairesel referanslar yüzünden burada yapamayız .

circularUncle

LOCALSTORAGE.CYCLICJSONsahiptir .stringifyve .parsesadece normal gibiJSON ama dairesel referanslarla nesnelerle çalışır. (Ayrıştırma (stringify (obj)) ve obj anlamına gelen "Works" (derin) eşittir ve özdeş 'iç eşitlikler' setlerine sahiptir)

Ancak kısayolları kullanabiliriz:

LOCALSTORAGE.setObject('latinUncles', obj)
recovered = LOCALSTORAGE.getObject('latinUncles')

O halde, recoveredaşağıdaki anlamda itiraz etmek için "aynı" olacaktır:

[
obj.L.L.v === recovered.L.L.v,
obj.L.R.v === recovered.L.R.v,
obj.R.L.v === recovered.R.L.v,
obj.R.R.L.v === recovered.R.R.L.v,
obj.R.R.R.v === recovered.R.R.R.v,
obj.R.L.uncle === obj.L,
obj.R.R.uncle === obj.L,
obj.R.R.L.uncle === obj.R.L,
obj.R.R.R.uncle === obj.R.L,
obj.L.L.uncle === obj.R,
obj.L.R.uncle === obj.R,
recovered.R.L.uncle === recovered.L,
recovered.R.R.uncle === recovered.L,
recovered.R.R.L.uncle === recovered.R.L,
recovered.R.R.R.uncle === recovered.R.L,
recovered.L.L.uncle === recovered.R,
recovered.L.R.uncle === recovered.R
]

İşte uygulanması LOCALSTORAGE

LOCALSTORAGE = (function(){
  "use strict";
  var ignore = [Boolean, Date, Number, RegExp, String];
  function primitive(item){
    if (typeof item === 'object'){
      if (item === null) { return true; }
      for (var i=0; i<ignore.length; i++){
        if (item instanceof ignore[i]) { return true; }
      }
      return false;
    } else {
      return true;
    }
  }
  function infant(value){
    return Array.isArray(value) ? [] : {};
  }
  function decycleIntoForest(object, replacer) {
    if (typeof replacer !== 'function'){
      replacer = function(x){ return x; }
    }
    object = replacer(object);
    if (primitive(object)) return object;
    var objects = [object];
    var forest  = [infant(object)];
    var bucket  = new WeakMap(); // bucket = inverse of objects 
    bucket.set(object, 0);    
    function addToBucket(obj){
      var result = objects.length;
      objects.push(obj);
      bucket.set(obj, result);
      return result;
    }
    function isInBucket(obj){ return bucket.has(obj); }
    function processNode(source, target){
      Object.keys(source).forEach(function(key){
        var value = replacer(source[key]);
        if (primitive(value)){
          target[key] = {value: value};
        } else {
          var ptr;
          if (isInBucket(value)){
            ptr = bucket.get(value);
          } else {
            ptr = addToBucket(value);
            var newTree = infant(value);
            forest.push(newTree);
            processNode(value, newTree);
          }
          target[key] = {pointer: ptr};
        }
      });
    }
    processNode(object, forest[0]);
    return forest;
  };
  function deForestIntoCycle(forest) {
    var objects = [];
    var objectRequested = [];
    var todo = [];
    function processTree(idx) {
      if (idx in objects) return objects[idx];
      if (objectRequested[idx]) return null;
      objectRequested[idx] = true;
      var tree = forest[idx];
      var node = Array.isArray(tree) ? [] : {};
      for (var key in tree) {
        var o = tree[key];
        if ('pointer' in o) {
          var ptr = o.pointer;
          var value = processTree(ptr);
          if (value === null) {
            todo.push({
              node: node,
              key: key,
              idx: ptr
            });
          } else {
            node[key] = value;
          }
        } else {
          if ('value' in o) {
            node[key] = o.value;
          } else {
            throw new Error('unexpected')
          }
        }
      }
      objects[idx] = node;
      return node;
    }
    var result = processTree(0);
    for (var i = 0; i < todo.length; i++) {
      var item = todo[i];
      item.node[item.key] = objects[item.idx];
    }
    return result;
  };
  var console = {
    log: function(x){
      var the = document.getElementById('the');
      the.textContent = the.textContent + '\n' + x;
	},
	delimiter: function(){
      var the = document.getElementById('the');
      the.textContent = the.textContent +
		'\n*******************************************';
	}
  }
  function logCyclicObjectToConsole(root) {
    var cycleFree = decycleIntoForest(root);
    var shown = cycleFree.map(function(tree, idx) {
      return false;
    });
    var indentIncrement = 4;
    function showItem(nodeSlot, indent, label) {
      var leadingSpaces = ' '.repeat(indent);
      var leadingSpacesPlus = ' '.repeat(indent + indentIncrement);
      if (shown[nodeSlot]) {
        console.log(leadingSpaces + label + ' ... see above (object #' + nodeSlot + ')');
      } else {
        console.log(leadingSpaces + label + ' object#' + nodeSlot);
        var tree = cycleFree[nodeSlot];
        shown[nodeSlot] = true;
        Object.keys(tree).forEach(function(key) {
          var entry = tree[key];
          if ('value' in entry) {
            console.log(leadingSpacesPlus + key + ": " + entry.value);
          } else {
            if ('pointer' in entry) {
              showItem(entry.pointer, indent + indentIncrement, key);
            }
          }
        });
      }
    }
	console.delimiter();
    showItem(0, 0, 'root');
  };
  function stringify(obj){
    return JSON.stringify(decycleIntoForest(obj));
  }
  function parse(str){
    return deForestIntoCycle(JSON.parse(str));
  }
  var CYCLICJSON = {
    decycleIntoForest: decycleIntoForest,
    deForestIntoCycle : deForestIntoCycle,
    logCyclicObjectToConsole: logCyclicObjectToConsole,
    stringify : stringify,
    parse : parse
  }
  function setObject(name, object){
    var str = stringify(object);
    localStorage.setItem(name, str);
  }
  function getObject(name){
    var str = localStorage.getItem(name);
    if (str===null) return null;
    return parse(str);
  }
  return {
    CYCLICJSON : CYCLICJSON,
    setObject  : setObject,
    getObject  : getObject
  }
})();
obj = {
	L: {
		L: { v: 'lorem' },
		R: { v: 'ipsum' }
	},
	R: {
		L: { v: 'dolor' },
		R: {
			L: { v: 'sit' },
			R: { v: 'amet' }
		}
	}
}
obj.R.L.uncle = obj.L;
obj.R.R.uncle = obj.L;
obj.R.R.L.uncle = obj.R.L;
obj.R.R.R.uncle = obj.R.L;
obj.L.L.uncle = obj.R;
obj.L.R.uncle = obj.R;

// LOCALSTORAGE.setObject('latinUncles', obj)
// recovered = LOCALSTORAGE.getObject('latinUncles')
// localStorage not available inside fiddle ):
LOCALSTORAGE.CYCLICJSON.logCyclicObjectToConsole(obj)
putIntoLS = LOCALSTORAGE.CYCLICJSON.stringify(obj);
recovered = LOCALSTORAGE.CYCLICJSON.parse(putIntoLS);
LOCALSTORAGE.CYCLICJSON.logCyclicObjectToConsole(recovered);

var the = document.getElementById('the');
the.textContent = the.textContent + '\n\n' +
JSON.stringify(
[
obj.L.L.v === recovered.L.L.v,
obj.L.R.v === recovered.L.R.v,
obj.R.L.v === recovered.R.L.v,
obj.R.R.L.v === recovered.R.R.L.v,
obj.R.R.R.v === recovered.R.R.R.v,
obj.R.L.uncle === obj.L,
obj.R.R.uncle === obj.L,
obj.R.R.L.uncle === obj.R.L,
obj.R.R.R.uncle === obj.R.L,
obj.L.L.uncle === obj.R,
obj.L.R.uncle === obj.R,
recovered.R.L.uncle === recovered.L,
recovered.R.R.uncle === recovered.L,
recovered.R.R.L.uncle === recovered.R.L,
recovered.R.R.R.uncle === recovered.R.L,
recovered.L.L.uncle === recovered.R,
recovered.L.R.uncle === recovered.R
]
)
<pre id='the'></pre>


-2

localStorage.setItem ('kullanıcı', JSON.stringify (kullanıcı));

Daha sonra onu mağazadan almak ve tekrar bir nesneye dönüştürmek için:

var user = JSON.parse (localStorage.getItem ('kullanıcı'));

Mağazanın tüm girişlerini silmemiz gerekirse şunları yapabiliriz:

localStorage.clear ();


3
Bu 10 yaşında bir soru. Cevabınızın diğer cevaplar tarafından kapsanmamış bir şey eklediğini düşünüyor musunuz?
Kristopher Johnson
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.