Was ist Localstorage?
Vor ein paar Tagen stellte ich fest, dass die Funktionsweise von Cookies in einem alten Projekt sehr seltsam war. Nach Rücksprache wollte ich einige Informationen zwischenspeichern, um die Übergabe von Parametern an die URL zu vermeiden, aber ich habe nicht über die Probleme nachgedacht, die Cookies mit sich bringen würden Ursache:
① Die Cookie-Größe ist auf etwa 4 KB begrenzt, was nicht zum Speichern von Geschäftsdaten geeignet ist
② Cookies werden jedes Mal zusammen mit HTTP-Transaktionen gesendet, was Bandbreite verschwendet
Wir führen mobile Projekte durch, daher ist die Technologie, die hier wirklich geeignet ist, Localstorage. Man kann sagen, dass es sich um eine Optimierung von Cookies handelt, mit der Daten bequem auf dem Client gespeichert werden können HTTP, aber das ist kein Problem:
① Die Größe von localstorage ist auf etwa 5 Millionen Zeichen begrenzt und verschiedene Browser sind inkonsistent
② Localstorage kann im Datenschutzmodus nicht gelesen werden
③ Das Wesentliche von localstorage ist das Lesen und Schreiben von Dateien, falls vorhanden Viele Daten bleiben hängen (Firefox wird das gleichzeitige Importieren von Daten in den Speicher beängstigend machen, wenn man darüber nachdenkt)
④ Localstorage kann nicht von Crawlern gecrawlt werden. Verwenden Sie es nicht, um die Übergabe von URL-Parametern vollständig zu ersetzen
Mängel verbergen nicht die Vorteile, die oben genannten Probleme können vermieden werden, daher sollte unser Fokus auf der Verwendung von Localstorage und der richtigen Verwendung liegen.
Nutzung von Localstorage
Grundkenntnisse
Es gibt zwei Arten von Localstorage-Speicherobjekten:
① sessionStrage: Sitzung bedeutet Sitzung hier bezieht sich auf den Zeitraum vom Betreten der Website bis zum Schließen der Website, wenn der Benutzer eine Website durchsucht.
② localStorage: Speichern Sie die Daten auf dem Client-Hardwaregerät, unabhängig davon, um was es sich handelt. Dies bedeutet, dass die Daten beim nächsten Einschalten des Computers immer noch vorhanden sind.
Der Unterschied zwischen den beiden besteht darin, dass eines für die vorübergehende Speicherung und das andere für die Langzeitspeicherung vorgesehen ist.
Hier ist ein einfacher Code, um seine grundlegende Verwendung zu veranschaulichen:
XML/HTML-CodeInhalt in die Zwischenablage kopieren
- <div id="msg" Stil="Rand: 10px 0; Rahmen: 1px schwarz; Innenraum: 10px; Breite: 300px;
- height: 100px;">
-
div>
-
<Eingabe Typ="Text" id="text" />
-
<select id="type" >
-
<Option Wert="session" >sessionStorageOption>
-
<Option Wert="lokal" >localStorageOption>
-
auswählen>
-
<button onclick="save( );">
-
保存数据Schaltfläche>
-
<button onclick="load( );">
-
读取数据Schaltfläche>
-
<script type="text/ Javascript">
-
var msg = document.getElementById('msg'),
-
text = document.getElementById('text'),
-
type = document.getElementById('type');
-
-
Funktion save() {
-
var str = text.value;
-
var t = type.value;
-
if (t == 'session') {
-
sessionStorage.setItem('msg', str);
-
} else {
-
localStorage.setItem('msg', str);
-
}
-
}
-
-
Funktion load() {
-
var t = type.value;
-
if (t == 'session') {
-
msg.innerHTML = sessionStorage.getItem('msg');
-
} else {
-
msg.innerHTML = localStorage.getItem('msg');
-
}
-
}
-
Skript>
真实场景
实际工作中对localstorage的使用一般有以下需求:
① 缓存一般信息,如搜索页的出发城市,达到城市,非实时定位信息
② 缓存城市列表数据,这个数据往往比较大
③ 每条缓存信息需要可追踪, 比如服务器通知城市数据更新, 这个时候在最近一次访问的时候要自动设置过期
④ 每条信息具有过期日期状态,在过期外时间需要由服务器拉取数据
XML/HTML-Code复制内容到剪贴板
-
define([], function () {
-
-
var Storage = _.inherit({
-
//Standardattribute
-
Eigenschaften: Funktion () {
-
-
//Proxy-Objekt, Standard ist localstorage
-
this.sProxy = window.localStorage;
-
//60 * 60 * 24 * 30 * 1000 -
ms ==30 Tage
-
this.defaultLifeTime = 2592000000;
-
//Der lokale Cache wird zum Speichern der Zuordnung zwischen allen Schlüsselwerten und Ablaufdaten des lokalen Speichers verwendet
-
this.keyCache-
= 'SYSTEM_KEY_TIMEOUT_MAP';
//Wenn die Cache-Kapazität voll ist, wird die Anzahl der Caches jedes Mal gelöscht -
- this.removeNum
= -
5;
}, -
-
assurance: function () { -
if (- this.sProxy
=== null) { -
throw 'sProxy-Eigenschaft nicht überschreiben';
}
-
},
-
-
initialisieren: Funktion (opts) {
-
this.propertys();
-
this.assert();
-
},
-
-
/*
-
Lokalen Speicher hinzufügen
-
Das Datenformat umfasst einen eindeutigen Schlüsselwert, eine JSON-Zeichenfolge, ein Ablaufdatum und ein Einzahlungsdatum
Das -
-Zeichen ist ein formatierter Anforderungsparameter, der verwendet wird, um neue Daten zurückzugeben, wenn dieselbe Anforderung unterschiedliche Parameter hat. Wenn die Liste beispielsweise die Stadt Peking ist und dann nach Shanghai gewechselt wird, wird das Tag beurteilt ist anders und aktualisiert die zwischengespeicherten Daten. Das Tag entspricht Signatur
-
Für jeden Schlüsselwert wird nur eine Information zwischengespeichert
-
*/
-
set: Funktion (Schlüssel, Wert, Timeout, Vorzeichen) {
-
var _d = neu Datum();
-
//Einzahlungsdatum
-
var indate = _d.getTime();
-
-
//Endlich gespeicherte Daten
-
var entity = null;
-
if (!timeout) { -
_d.setTime(_d.getTime() this.defaultLifeTime); -
-
timeout = _d.getTime();
} -
-
// -
this.setKeyCache(key, timeout); -
-
entity = this.buildStorageObj(value, indate, timeout, sign);
-
versuchen Sie es mit { -
this.sProxy.setItem(key, JSON.stringify(entity)); -
true zurückgeben; -
} Catch (e) { -
//Wenn der lokale Speicher voll ist, alles löschen -
if (-
e.name == 'QuotaExceededError') {
// this.sProxy.clear(); -
//Wenn der lokale Speicher voll ist, wählen Sie die zu löschenden Daten aus, die am nächsten an der Ablaufzeit liegen, aber es fühlt sich besser an, als alles zu löschen zeitaufwändiger sein, innerhalb von 100 ms -
if (!this.removeLastCache()) throw 'Die diesmal gespeicherte Datenmenge ist zu groß';
-
this.set(key, value, timeout, sign);
-
console && console.log(e); -
}
-
gibt false zurück;
-
},
-
-
//Abgelaufenen Cache löschen
-
RemoveOverdueCache: Funktion () {
-
var tmpObj = null, i, len;
-
var -
now = new Date().getTime();
//Das Schlüssel-Wert-Paar abrufen -
var -
cacheStr = this.sProxy.getItem(this.keyCache);
var -
cacheMap = [];
var
newMap-
= [];
if (!cacheStr) {
zurück; -
} -
-
- cacheMap
= -
JSON.parse(cacheStr);
für (- i
= -
0, len = cacheMap.length; i < len; >
tmpObj =
- cacheMap[i];
if (tmpObj.timeout < now
- ) {
this.sProxy.removeItem(tmpObj.key);
} else {
- newMap.push(tmpObj);
-
}
-
this.sProxy.setItem(this.keyCache, JSON.stringify(newMap));
-
-
},
-
-
RemoveLastCache: Funktion () {
-
var i, len;
-
var num = this.removeNum ||
-
//Das Schlüssel-Wert-Paar abrufen -
var -
cacheStr = this.sProxy.getItem(this.keyCache);
var -
cacheMap = [];
var
delMap-
= [];
//Zeigt an, dass der Speicher zu groß ist -
if (!cacheStr) return false; -
-
cacheMap.sort(function (a, b) { -
return a.timeout - b.timeout; -
}); -
-
//Welche Daten wurden gelöscht -
- delMap
= -
cacheMap.splice(0, num);
für (i
= -
0, len = delMap.length; i < len ) {
this.sProxy.removeItem(delMap[i].key);
} -
-
this.sProxy.setItem(this.keyCache, JSON.stringify(cacheMap)); -
true zurückgeben; -
}, -
-
setKeyCache: Funktion (Schlüssel, Timeout) { -
if (!key || !timeout || timeout - <
-
new Date().getTime( )) zurück;
var i, len, tmpObj;
-
//Die aktuell zwischengespeicherte Schlüsselwertzeichenfolge abrufen
- var
oldstr- =
this-
.sProxy.getItem(
var oldMap = [];
//Ob der aktuelle Schlüssel bereits existiert -
var flag
= - false
;
-
var obj = {};
-
obj.key = key;
-
obj.timeout = timeout;
-
-
if (oldstr) {
-
oldMap = JSON.parse(oldstr);
-
if (!_.isArray(oldMap)) oldMap = [];
-
}
-
-
für (i = 0, len = oldMap.length; i < len; i ) {
-
tmpObj = oldMap[i];
-
if (tmpObj.key == key) {
-
oldMap[i] = obj;
-
flag = true;
-
Pause;
-
}
-
}
-
if (!flag) oldMap.push(obj);
-
//最后将新数组放到缓存中
-
this.sProxy.setItem(this.keyCache, JSON.stringify(oldMap));
-
-
},
-
-
buildStorageObj: Funktion (Wert, Indate, Timeout, Sign) {
-
var obj = {
-
Wert: Wert,
-
timeout: timeout,
-
Zeichen: Zeichen,
-
indate: indate
-
};
-
return obj;
-
},
-
-
get: Funktion (Schlüssel, Zeichen) {
-
var result, now = new Date().getTime(
-
versuchen Sie es mit {
-
result = this.sProxy.getItem(key);
if (!result) return null; -
-
result = JSON.parse(result);
-
//Datenablauf -
if (result.timeout -
< now) return null;
-
//Signaturüberprüfung ist erforderlich
-
if (sign) {
- if (
sign-
=== result.sign)
return result.value;
-
null zurückgeben
-
} else {
-
return result.value;
-
-
} Catch (e) { -
console && console.log(e); -
} -
null zurückgeben -
}, -
-
//Signatur erhalten -
getSign: Funktion (Schlüssel) { -
var result, - sign
= -
null;
versuchen Sie es mit {
result- =
this-
.sProxy.getItem(key);
if (result) {
result
= - JSON
.parse(result); -
sign = result
&& result.sign -
} Catch (e) {
console && console.log(e);
-
}
-
Rückgabezeichen;
-
},
-
-
remove: function (key) {
-
return this.sProxy.removeItem(key);
-
},
-
-
clear: function () {
-
this.sProxy.clear();
-
}
-
});
-
-
Storage.getInstance = Funktion () {
-
if (this.instance) {
-
return this.instance;
-
} else {
-
return this.instance = new this();
-
}
-
};
-
-
zurück Lagerung;
-
-
});
这段代码包含了localstorage的基本操作,并且对以上问题做了处理,而真实的使用还要再抽象:
XML/HTML-Code复制内容到剪贴板
-
define(['AbstractStorage'], function (AbstractStorage) {
-
-
var Store = _.inherit({
-
//Standardattribute
-
Eigenschaften: Funktion () {
-
-
//Jedes Objekt muss einen Speicherschlüssel haben und kann nicht wiederholt werden
-
this.key = null;
-
//Der Standardlebenszyklus eines Datenelements, S ist Sekunden, M ist Minuten, D ist Tage -
-
this.lifeTime = '30M';
-
//Standard-Rückgabedaten
- //
this.defaultData-
= null;
-
//Proxy-Objekt, lokales Speicherobjekt
-
this.sProxy-
= new AbstractStorage();
-
},
-
-
setOption: Funktion (Optionen) {
-
_.extend(this, Optionen);
-
},
-
-
assurance: function () {
- if (
this.key-
=== null) {
throw 'Schlüsseleigenschaft nicht überschreiben';
-
}
- if (
this.sProxy-
=== null) {
throw 'sProxy-Eigenschaft nicht überschreiben';
} -
}, -
-
initialisieren: Funktion (opts) { -
this.propertys(); -
this.setOption(opts); -
this.assert(); -
},
-
-
_getLifeTime: function () {
-
var timeout = 0;
-
var str = this.lifeTime;
-
var unit = str.charAt(str.length - 1);
-
var num = str.substring(0, str.length - 1);
-
var Karte = {
-
D: 86400,
-
H: 3600,
-
M: 60,
-
S: 1
-
};
-
if (typeof unit == 'string') {
-
unitunit = unit.toUpperCase();
-
}
-
timeout = num;
-
if (unit) timeout = Map[unit];
-
-
//单位为毫秒
-
return num * timeout * 1000 ;
-
},
-
-
//缓存数据
-
set: Funktion (Wert, Vorzeichen) {
-
//获取过期时间
-
var timeout = new Date();
-
timeout.setTime(timeout.getTime() this._getLifeTime());
-
this.sProxy.set(this.key, value, timeout.getTime(), sign);
-
},
-
-
//设置单个属性
-
setAttr: Funktion (Name, Wert, Zeichen) {
-
var key, obj;
-
if (_.isObject(name)) {
-
für (Namen eingeben) {
-
if (name.hasOwnProperty(key)) this.setAttr(k, name[k], value);
-
}
-
zurück;
-
}
-
-
if (!sign) sign = this.getSign();
-
-
//获取当前对象
-
obj = this.get(sign) || {};
-
if (!obj) return;
-
obj[name] = value;
-
this.set(obj, sign);
-
-
},
-
-
getSign: function () {
-
return this.sProxy.getSign(this.key);
-
},
-
-
remove: function () {
-
this.sProxy.remove(this.key);
-
},
-
-
removeAttr: function (attrName) {
-
var obj = this.get() || {};
-
if (obj[attrName]) {
-
delete obj[attrName];
-
}
-
this.set(obj);
-
},
-
-
get: function (sign) {
-
var result = [], isEmpty = true, a;
-
var obj = this.sProxy.get(this.key, sign);
-
var type = typeof obj;
-
var o = { 'string': true, 'number': true, 'boolean': true };
-
if (o[type]) return obj;
-
-
if (_.isArray(obj)) {
-
für (var i = 0, len = obj.length; i < len; i ) {
-
result[i] = obj[i];
-
}
-
} else if (_.isObject(obj)) {
-
result = obj;
-
}
-
-
für (ein Ergebnis) {
-
isEmpty = false;
-
Pause;
-
}
-
return !isEmpty ? Ergebnis : null;
-
},
-
-
getAttr: function (attrName, tag) {
-
var obj = this.get(tag);
-
var attrVal = null;
-
if (obj) {
-
attrVal = obj[attrName];
-
}
-
return attrVal;
-
}
-
-
});
-
-
Store.getInstance = Funktion () {
-
if (this.instance) {
-
return this.instance;
-
} else {
-
return this.instance = new this();
-
}
-
};
-
-
Retouren-Shop;
-
});
我们真实使用的时候是使用store这个类操作localstorage,代码结束简单测试:
存储完成, 以后都不会走请求, 于是今天的代码基本结束, 最后在Android Hybrid中有一后退按钮, 此按钮一旦按下会回到上一个页面,这个时候里面的localstorage可能会读取失效!一个简单不靠谱的解决方案是在webapp中加入:
XML/HTML-Code复制内容到剪贴板
-
window.onunload = function () { };//适合单页应用,不要问我为什么,我也不知道
结语
localstorage是移动开发必不可少的技术点,需要深入了解,具体业务代码后续会放到git上,有兴趣的朋友可以去了解