Qu'est-ce que le stockage local
Il y a quelques jours, j'ai trouvé que le fonctionnement des cookies était très étrange dans un ancien projet. Après consultation, j'ai souhaité mettre en cache certaines informations pour éviter de passer des paramètres sur l'URL, mais je n'ai pas envisagé les problèmes que poseraient les cookies. cause :
① La taille des cookies est limitée à environ 4 Ko, ce qui n'est pas adapté au stockage de données professionnelles
② Les cookies sont envoyés à chaque fois avec des transactions HTTP, ce qui gaspille de la bande passante
Nous réalisons des projets mobiles, donc la technologie qui est vraiment appropriée à utiliser ici est le stockage local. On peut dire que le stockage local est une optimisation des cookies. Il peut être utilisé pour stocker facilement des données sur le client et ne sera pas transmis avec. HTTP, mais ce n'est pas le cas. Pas de problème :
① La taille du stockage local est limitée à environ 5 millions de caractères et les différents navigateurs sont incohérents
② Le stockage local ne peut pas être lu en mode confidentialité
③ L'essence du stockage local est de lire et d'écrire des fichiers s'il y en a. beaucoup de données, elles seront bloquées (Firefox importera des données en mémoire en même temps est effrayant quand on y pense)
④ le stockage local ne peut pas être exploré par les robots d'exploration, ne l'utilisez pas pour remplacer complètement le passage des paramètres d'URL
Les défauts ne cachent pas les avantages, les problèmes ci-dessus peuvent être évités, nous devons donc nous concentrer sur la façon d'utiliser le stockage local et sur la manière de l'utiliser correctement.
Utilisation du stockage local
Connaissances de base
Il existe deux types d'objets de stockage local :
① sessionStrage : session signifie session. La session fait ici référence à la période de temps allant de l'entrée sur le site Web à la fermeture du site Web lorsque l'utilisateur navigue sur un site Web. La période de validité de l'objet de session n'est que limitée.
② localStorage : enregistrez les données sur le périphérique matériel client, quel qu'il soit, ce qui signifie que les données seront toujours là lors de la prochaine mise sous tension de l'ordinateur.
La différence entre les deux est que l'un est destiné au stockage temporaire et l'autre au stockage à long terme.
Voici un code simple pour illustrer son utilisation de base :
Code XML/HTMLCopier le contenu dans le presse-papiers
- <div id="msg" style="marge : 10px 0; bordure : 1px noir uni ; remplissage : 10px; largeur : 300px ;
- hauteur : 100px;">
-
div>
-
<entrée type="texte" id="texte" />
-
<sélectionner id="type" >
-
<option valeur="session" >sessionStorageoption>
-
<option valeur="local" >localStorageoption>
-
sélectionner>
-
<bouton on clique="enregistrer( );">
-
保存数据bouton>
-
<bouton onclique="charger( );">
-
读取数据bouton>
-
<script type="texte/ javascript">
-
var msg = document.getElementById('msg'),
-
text = document.getElementById('text'),
-
type = document.getElementById('type');
-
-
fonction save() {
-
var str = text.value;
-
var t = type.value;
-
si (t == 'session') {
-
sessionStorage.setItem('msg', str);
-
} autre {
-
localStorage.setItem('msg', str);
-
}
-
}
-
-
fonction load() {
-
var t = type.value;
-
si (t == 'session') {
-
msg.innerHTML = sessionStorage.getItem('msg');
-
} autre {
-
msg.innerHTML = localStorage.getItem('msg');
-
}
-
}
-
script>
真实场景
实际工作中对localstorage的使用一般有以下需求:
① 缓存一般信息,如搜索页的出发城市,达到城市,非实时定位信息
② 缓存城市列表数据,这个数据往往比较大
③ 每条缓存信息需要可追踪,比如服务器通知城市数据更新,这个时候在最近一次访问的时候要自动设置过期
④ 每条信息具有过期日期状态,在过期外时间需要由服务器拉取数据
Code XML/HTML复制内容到剪贴板
-
define([], function() {
-
-
var Stockage = _.inherit({
-
//Attributs par défaut
-
propriétés : fonction () {
-
-
//Objet proxy, la valeur par défaut est localstorage
-
this.sProxy = fenêtre.localStorage;
-
-
//60 * 60 * 24 * 30 * 1000 ms ==30 jours
-
this.defaultLifeTime = 2592000000
-
-
//Le cache local est utilisé pour stocker le mappage entre toutes les valeurs de clé de stockage local et les dates d'expiration
-
this.keyCache = 'SYSTEM_KEY_TIMEOUT_MAP';
-
//Lorsque la capacité du cache est pleine, le nombre de caches supprimés à chaque fois -
-
this.removeNum = 5 ;
-
}, -
-
assert: function () { -
if (-
this.sProxy === null) {
lancer « ne pas remplacer la propriété sProxy » ; -
} -
}, -
-
initialiser : fonction (opts) { -
this.propertys(); -
this.assert(); -
},
-
-
/*
-
Ajouter un stockage local
-
Le format des données comprend une valeur de clé unique, une chaîne JSON, une date d'expiration et une date de dépôt
Le signe -
est un paramètre de requête formaté, utilisé pour renvoyer de nouvelles données lorsque la même requête a des paramètres différents. Par exemple, si la liste est la ville de Pékin, puis basculée vers Shanghai, il jugera que la balise. est différent et met à jour les données mises en cache. La balise est équivalente à Signature
.
-
Une seule information sera mise en cache pour chaque valeur clé
-
*/
-
set : fonction (clé, valeur, délai d'attente, signe) {
-
var _d = nouveau Date();
-
//Date de dépôt
-
var indate = _d.getTime();
-
-
//Données enfin enregistrées
-
var entité = null
;
-
-
si (!timeout) {
-
_d.setTime(_d.getTime() this.defaultLifeTime);
-
timeout = _d.getTime();
-
}
-
-
//
-
this.setKeyCache(clé, délai d'attente);
-
entity = this.buildStorageObj(value, indate, timeout, sign); >
-
essayez { -
this.sProxy.setItem(key, JSON.stringify(entity)); -
renvoie vrai; -
} capture(e) { -
//Lorsque le stockage local est plein, effacez tout -
if (-
e.name == 'QuotaExceededError') {
// this.sProxy.clear(); -
//Lorsque le stockage local est plein, sélectionnez les données les plus proches de l'heure d'expiration à supprimer. Cela aura également un certain impact, mais c'est mieux que de tout effacer. S'il y a trop de caches, ce processus le fera. prendre plus de temps, dans les 100 ms -
if (!this.removeLastCache()) throw 'La quantité de données stockées cette fois est trop importante' -
this.set(clé, valeur, délai d'attente, signe - );
-
console && console.log(e);
-
}
-
return false;
-
},
-
-
//Supprimer le cache expiré
-
removeOverdueCache : function() {
-
var tmpObj = null, je, len
-
-
var maintenant = nouveau Date().getTime();
//Obtenir la paire clé-valeur -
var -
cacheStr = this.sProxy.getItem(this.keyCache);
var
cacheMap-
= [];
var newMap
= [];
-
if (!cacheStr) {
retour;
-
}
-
-
cacheMap- =
JSON-
.parse(cacheStr);
pour (i
= - 0
, -
len = cacheMap.length; je < len ; >
tmpObj = cacheMap[i];
-
if (tmpObj.timeout < maintenant) {
-
this.sProxy.removeItem(tmpObj.key);
} autre {
newMap.push(tmpObj);
-
- }
- this.sProxy.setItem(this.keyCache, JSON.stringify(newMap));
-
- },
-
-
removeLastCache : function() {
-
var je, len
-
var num = this.removeNum ||
-
-
//Obtenir la paire clé-valeur
-
var cacheStr = this.sProxy.getItem(this.keyCache);
var -
cacheMap = [];
var
delMap-
= [];
//Indique que le stockage est trop grand -
if (!cacheStr) renvoie false -
-
cacheMap.sort(function (a, b) { -
return a.timeout - b.timeout -
}); -
-
//Quelles données ont été supprimées -
- delMap
= -
cacheMap.splice(0, num);
pour (i =
0-
, len = delMap.length; je < len ; >
this.sProxy.removeItem(delMap[i].key);
}
-
- this.sProxy.setItem(this.keyCache, JSON.stringify(cacheMap));
- renvoie vrai;
- },
-
- setKeyCache : fonction (clé, délai d'attente) {
- if (!key || !timeout || timeout <
- nouveau
- Date().getTime( )) retour;
var i, len, tmpObj
- //Obtenir la chaîne de valeur de clé actuellement mise en cache
- var oldstr
- = this
- .sProxy.getItem(this.keyCache);
var oldMap = [];
//Si la clé actuelle existe déjà
- var drapeau = faux
- ;
- var obj = {};
-
obj.key = clé ;
-
obj.timeout = timeout ;
-
-
si (oldstr) {
-
oldMap = JSON.parse(oldstr);
-
if (!_.isArray(oldMap)) oldMap = [];
-
}
-
-
pour (i = 0, len = oldMap.length; i < len; i ) {
-
tmpObj = oldMap[i];
-
if (tmpObj.key == key) {
-
oldMap[i] = obj;
-
drapeau = vrai;
-
pause ;
-
}
-
}
-
if (!flag) oldMap.push(obj);
-
//最后将新数组放到缓存中
-
this.sProxy.setItem(this.keyCache, JSON.stringify(oldMap));
-
-
},
-
-
buildStorageObj : fonction (valeur, date, délai d'attente, signe) {
-
var obj = {
-
valeur : valeur,
-
délai d'expiration : délai d'expiration,
-
signe : signe,
-
indate: indate
-
} ;
-
return obj ;
-
},
-
-
get : fonction (clé, signe) {
-
résultat var, maintenant = nouveau Date().getTime();
essayez { -
-
résultat = ce.sProxy.getItem(key);
if (!result) renvoie null
-
résultat-
= JSON.parse(résultat);
//Expiration des données -
if (result.timeout - <
-
maintenant) renvoie null
//Une vérification de la signature est requise -
si (signe) { -
if (- signe
=== result.sign) -
return result.value
renvoie null -
} autre { -
return result.value -
-
-
} capture(e) {
-
console && console.log(e);
-
}
-
renvoie null
-
},
-
-
//Obtenir une signature
-
getSign : fonction (clé) {
- résultat var,
signe- =
null-
;
essayez {
résultat- =
ce-
.sProxy.getItem(key);
si (résultat) {
résultat
= - JSON
.parse(résultat);
-
signe = résultat && résultat.sign
-
} capture(e) {
console && console.log(e);
}
-
panneau de retour ;
-
},
-
-
supprimer : fonction (touche) {
-
return this.sProxy.removeItem(key);
-
},
-
-
clear : function () {
-
this.sProxy.clear();
-
}
-
});
-
-
Storage.getInstance = fonction () {
-
si (cette.instance) {
-
return this.instance ;
-
} autre {
-
return this.instance = new this();
-
}
-
} ;
-
-
retour Stockage ;
-
-
});
Code XML/HTML
复制内容到剪贴板
-
define(['AbstractStorage'], function (AbstractStorage) {
-
-
var Store = _.inherit({
-
//Attributs par défaut
-
propriétés : fonction () {
-
-
//Chaque objet doit avoir une clé de stockage et ne peut pas être répété
-
this.key = null
;
-
-
//Le cycle de vie par défaut d'une donnée, S correspond aux secondes, M aux minutes, D aux jours
-
this.lifeTime = '30M'
;
-
-
//Données de retour par défaut
-
// this.defaultData = null
;
-
-
//Objet proxy, objet localstorage
-
this.sProxy = nouveau AbstractStorage();
-
-
},
-
-
setOption : fonction (options) {
-
_.extend(ce, options);
-
},
-
-
assert: function () {
-
if (this.key === null) {
-
lancer « ne pas remplacer la propriété clé » ;
-
}
-
if (this.sProxy === null) {
-
lancer « ne pas remplacer la propriété sProxy » ;
-
}
-
},
-
-
initialiser : fonction (opts) {
-
this.propertys();
-
this.setOption(opts);
-
this.assert();
-
},
-
-
_getLifeTime: function () {
-
var délai d'attente = 0 ;
-
var str = ce.lifeTime ;
-
var unit = str.charAt(str.length - 1);
-
var num = str.substring(0, str.length - 1);
-
var Carte = {
-
D : 86400,
-
H : 3600,
-
M : 60,
-
S : 1
-
} ;
-
if (type d'unité == 'chaîne') {
-
unitéunité = unit.toUpperCase();
-
}
-
délai d'expiration = num ;
-
si (unité) délai d'attente = Carte[unité] ;
-
-
//单位为毫秒
-
retour num * timeout * 1000 ;
-
},
-
-
//缓存数据
-
set : fonction (valeur, signe) {
-
//获取过期时间
-
var délai d'expiration = nouveau Date();
-
timeout.setTime(timeout.getTime() this._getLifeTime());
-
this.sProxy.set(this.key, value, timeout.getTime(), sign);
-
},
-
-
//设置单个属性
-
setAttr : fonction (nom, valeur, signe) {
-
clé var , obj ;
-
if (_.isObject(name)) {
-
pour (entrez le nom) {
-
if (name.hasOwnProperty(key)) this.setAttr(k, name[k], value);
-
}
-
retour ;
-
}
-
-
if (!sign) sign = this.getSign();
-
-
//获取当前对象
-
obj = ceci.get(signe) || {} ;
-
if (!obj) retour ;
-
obj[nom] = valeur ;
-
this.set(obj, sign);
-
-
},
-
-
getSign: function () {
-
return this.sProxy.getSign(this.key);
-
},
-
-
supprimer : function () {
-
this.sProxy.remove(this.key);
-
},
-
-
removeAttr : function (attrName) {
-
var obj = this.get() || {} ;
-
if (obj[attrName]) {
-
supprimer obj[attrName] ;
-
}
-
this.set(obj);
-
},
-
-
obtenir : fonction (signe) {
-
var result = [], isEmpty = true, une ;
-
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)) {
-
pour (var i = 0, len = obj.length; i < len; i ) {
-
result[i] = obj[i];
-
}
-
} else if (_.isObject(obj)) {
-
résultat = obj;
-
}
-
-
pour (un en résultat) {
-
isEmpty = false;
-
pause ;
-
}
-
revenir !isEmpty ? résultat : nul ;
-
},
-
-
getAttr: function (attrName, tag) {
-
var obj = this.get(tag);
-
var attrVal = null;
-
si (obj) {
-
attrVal = obj[attrName];
-
}
-
return attrVal ;
-
}
-
-
});
-
-
Store.getInstance = fonction () {
-
si (cette.instance) {
-
return this.instance ;
-
} autre {
-
return this.instance = new this();
-
}
-
} ;
-
-
retour Magasin ;
-
});
我们真实使用的时候是使用store这个类操作localstorage,代码结束简单测试:
Pour Android Hybrid Le stockage local et le stockage local失效!一个简单不靠谱的解决方案是在webapp中加入:
Code XML/HTML复制内容到剪贴板
-
window.onunload = function () { };//适合单页应用,不要问我为什么,我也不知道
结语
localstorage是移动开发必不可少的技术点,需要深入了解,具体业务代码后续会放到git上,有兴趣的朋友可以去了解