ローカルストレージとは
数日前、古いプロジェクトで Cookie の動作が非常に奇妙なことに気づきました。相談した結果、URL にパラメータを渡さないように情報をキャッシュしたいと思いましたが、Cookie が引き起こす問題については考慮していませんでした。原因:
① Cookie のサイズは約 4k に制限されており、ビジネスデータの保存には適していません
② Cookie は毎回 HTTP トランザクションと一緒に送信されるため、帯域幅が無駄に消費されます
私たちはモバイルプロジェクトを行っているため、ここで使用するのに本当に適したテクノロジーはローカルストレージです。ローカルストレージは、クライアント上にデータを保存するために使用でき、データは送信されません。 HTTP ですが、問題ありません:
① localstorage のサイズは約 500 万文字に制限されており、異なるブラウザでは一貫性がありません
② Localstorage はプライバシー モードでは読み取れません
③ localstorage の本質は、ファイルがあれば読み書きすることです。データが大量にあるとスタックしてしまいます (Firefox は一度にデータをメモリにインポートすることを考えると恐ろしいです)
④ localstorage はクローラーによってクロールされません。URL パラメーターの受け渡しを完全に置き換える目的で使用しないでください
欠点は利点を隠すものではありません。上記の問題は回避できるため、ローカルストレージの使用方法とそれを正しく使用する方法に重点を置く必要があります。
localstorageの使い方
基礎知識
localstorage ストレージ オブジェクトには 2 つのタイプがあります:
① sessionStrage: セッションとは、ユーザーがウェブサイトを閲覧する際に、ウェブサイトにアクセスしてからウェブサイトを閉じるまでの期間を指します。セッションオブジェクトの有効期間はごくわずかです。
② localStorage: データが何であれ、クライアント ハードウェア デバイスにデータを保存します。これは、次回コンピューターの電源を入れたときにもデータがまだそこにあることを意味します。
2 つの違いは、1 つは一時保管用で、もう 1 つは長期保管用であることです。
基本的な使用法を示す簡単なコードを次に示します。
XML/HTML コードコンテンツをクリップボードにコピー
- <div id="msg" スタイル="margin: 10px 0; border: 1px solid black; padding: 10px; width: 300px;
- 高さ: 100px;">
-
div>
-
<入力 type="テキスト" id="テキスト" />
-
<select id="type" >
- <オプション 値="セッション" >セッションストレージオプション>
-
<オプション 値="ローカル" >localStorageオプション>
-
選択>
- <ボタン クリック="save( );">
- データ保存ボタン>
-
<ボタン onclick="load( );">
- 读取数据ボタン>
-
<スクリプト type="text/ javascript">
-
var msg = ドキュメント.getElementById('msg'),
-
テキスト = ドキュメント.getElementById('text'),
-
タイプ = ドキュメント.getElementById('type');
-
-
関数 save() {
-
var str = text.value;
-
var t = type.value;
-
if (t == 'セッション') {
-
sessionStorage.setItem('msg', str);
-
} else {
-
localStorage.setItem('msg', str);
-
}
-
}
-
-
関数 load() {
-
var t = type.value;
-
if (t == 'セッション') {
-
msg.innerHTML = sessionStorage.getItem('msg');
-
} else {
-
msg.innerHTML = localStorage.getItem('msg');
-
}
-
}
-
スクリプト>
真实场景
实际作業中におけるローカルストレージの使用一般には以下の要件があります:
①缓存一般信息,如搜索页的出城市,到城市,非实時定位信息
② 缓存城市列表データベース、这个データ往往比较大
③每条缓存信息要可追跡,比如服务器通知城市データ更新,这時候最近访问的時候要自动設置过期
④ 每条信息有期日期状態态,期期外時間期間需要服务器拉取データ
XML/HTML コード复制コンテンツ到剪贴板
-
define([], function () {
-
-
var ストレージ = _.inherit({
-
//デフォルト属性
-
プロパティ: function () {
-
-
//プロキシ オブジェクト、デフォルトは localstorage
-
this.sProxy = ウィンドウ.localStorage;
-
//60 * 60 * 24 * 30 * 1000 -
ms ==30 日
-
this.defaultLifeTime = 2592000000 ;
-
//ローカル キャッシュは、すべての localstorage キー値と有効期限間のマッピングを保存するために使用されます
-
this.keyCache-
= 'SYSTEM_KEY_TIMEOUT_MAP' ;
//キャッシュ容量がいっぱいになった場合、毎回削除されるキャッシュの数 -
- this.removeNum
= -
5;
}、
-
-
アサート: function () {
- if (
this.sProxy-
=== null) {
-
throw 'sProxy プロパティをオーバーライドしません' ;
}
-
}、
-
-
初期化: function (opts) {
-
this.propertys();
-
this.assert();
-
}、
-
-
/*
-
ローカルストレージを追加
-
データ形式には、一意のキー値、JSON 文字列、有効期限、入金日が含まれます
-
記号は書式設定されたリクエスト パラメータで、同じリクエストに異なるパラメータがある場合に新しいデータを返すために使用されます。たとえば、リストが北京市であった場合に上海に切り替わった場合、タグであると判断されます。は異なり、キャッシュされたデータを更新します。タグは署名
と同等です。
-
各キー値に対して 1 つの情報のみがキャッシュされます
-
*/
-
set: 関数 (キー、値、タイムアウト、符号) {
-
var _d = 新しい Date();
//入金日 -
var -
indate = _d.getTime();
-
//最後にデータを保存しました
- var
エンティティ-
= null;
if (!timeout) { -
_d.setTime(_d.getTime() this.defaultLifeTime); -
- タイムアウト
= -
_d.getTime();
}
-
//
-
this.setKeyCache(キー, タイムアウト)
-
エンティティ- =
this-
.buildStorageObj(値、更新、タイムアウト、符号); >
試してみましょう {
this.sProxy.setItem(key, JSON.stringify(entity)); -
true を返します。-
} catch (e) { -
//ローカルストレージがいっぱいになったら、すべてクリアします -
if (- e.name
== 'QuotaExceededError') { -
// this.sProxy.clear(); -
//ローカルストレージがいっぱいの場合、有効期限に最も近いデータを選択して削除します。これも多少の影響はありますが、キャッシュが多すぎる場合は、このプロセスがすべてクリアされるよりも良いと感じます。 100 ミリ秒以内に、さらに時間がかかります
if (!this.removeLastCache()) throw '今回保存されたデータの量が多すぎます'; -
this.set(キー、値、タイムアウト、符号); -
- コンソール && console.log(e);
}
-
は false を返します。
-
}、
-
-
//期限切れのキャッシュを削除
-
RemoveOverdueCache: function () {
-
var tmpObj = null, i, len;
-
var -
now = new Date().getTime();
//キーと値のペアを取得します
- var
cacheStr-
= this.sProxy.getItem(this.keyCache);
var cacheMap
= [];
-
var newMap = [];
if (!cacheStr) { -
戻る
} -
-
- cacheMap
= - JSON
.parse(cacheStr);
-
for (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: function () {
-
変数 i、レン
-
var num = this.removeNum ||
-
-
//キーと値のペアを取得します
-
var cacheStr = this.sProxy.getItem(this.keyCache);
var -
cacheMap = [];
var
delMap-
= [];
//ストレージが大きすぎることを示します -
if (!cacheStr) が false を返す -
-
cacheMap.sort(function (a, b) { -
a.timeout - b.timeout を返します -
}); -
-
//削除されたデータ -
- delMap
= -
cacheMap.splice(0, num);
for (i =
0-
, len = delMap.length; i < len; >
this.sProxy.removeItem(delMap[i].key);
}
-
- this.sProxy.setItem(this.keyCache, JSON.stringify(cacheMap));
- true を返します。
- }、
-
- setKeyCache: function (key, timeout) {
- if (!key || !timeout || timeout <
- new
- Date().getTime( )) 戻る;
var i、len、tmpObj;
- //現在キャッシュされているキー値文字列を取得します
- var oldstr
- = this
- .sProxy.getItem(this.keyCache);
var oldMap = [];
//現在のキーがすでに存在するかどうか
- var フラグ = false
- ;
var
- obj = {};
-
obj.key = キー;
-
obj.timeout = タイムアウト;
-
-
if (oldstr) {
-
oldMap = JSON.parse(oldstr);
-
if (!_.isArray(oldMap)) oldMap = [];
-
}
-
-
for (i = 0, len = oldMap.length; i < len; i ) {
-
tmpObj = oldMap[i];
-
if (tmpObj.key == key) {
-
oldMap[i] = obj;
-
フラグ = true;
-
休憩;
-
}
-
}
-
if (!flag) oldMap.push(obj);
-
//最後将新数组を缓存中に放出
-
this.sProxy.setItem(this.keyCache, JSON.stringify(oldMap));
-
-
}、
-
-
buildStorageObj: function (value, indate, timeout, sign) {
-
var obj = {
-
値: 値、
-
タイムアウト: タイムアウト、
-
記号: 記号、
-
indate: indate
-
};
-
オブジェクトを返す;
-
}、
-
-
get: function (key,sign) {
-
var result、now = new Date().getTime();
試してみましょう { -
-
結果 = この.sProxy.getItem(key);
if (!result) が null を返す
-
結果-
= JSON.parse(結果);
//データの有効期限 -
if (result.timeout - <
-
now)
//署名検証が必要です -
if (符号) { -
if (- sign
=== result.sign) -
結果の値を返します
null を返します。-
} else { -
結果の値を返します -
-
-
} catch (e) {
- コンソール && console.log(e);
} -
null を返します。-
}、-
-
//署名を取得 -
getSign: function (key) { -
var 結果、- sign
= -
null
;
-
試してみましょう {
結果 =
この- .sProxy.getItem(key);
if (結果) { -
結果 = JSON
.parse(結果);
-
sign-
= result && result.sign
} catch (e) { -
コンソール && console.log(e);
}
-
リターン 記号;
-
}、
-
-
削除: 関数 (キー) {
-
return this.sProxy.removeItem(key);
-
}、
-
-
clear: function () {
-
this.sProxy.clear();
-
}
-
});
-
-
Storage.getInstance = 関数 () {
-
if (this.instance) {
-
this.instance を返す;
-
} else {
-
return this.instance = new this();
-
}
-
};
-
-
ストレージを返す;
-
-
});
このセグメントコードにはローカルストレージの基本的な操作が含まれており、上記の処理が実行されているため、実際の使用はさらに抽象化されます:
XML/HTML コード复制コンテンツ到剪贴板
-
define(['AbstractStorage'], function (AbstractStorage) {
-
-
var ストア = _.inherit({
-
//デフォルト属性
-
プロパティ: function () {
-
-
//各オブジェクトにはストレージ キーが必要であり、繰り返すことはできません
-
this.key = null;
-
//データのデフォルトのライフサイクル、S は秒、M は分、D は日 -
-
this.lifeTime = '30M';
-
//デフォルトの戻りデータ
- //
this.defaultData-
= null;
//プロキシ オブジェクト、ローカルストレージ オブジェクト -
- this.sProxy
= -
new AbstractStorage();
}、
-
-
setOption: 関数 (オプション) {
-
_.extend(this, options)
;
-
}、
-
-
アサート: function () {
- if (
this.key-
=== null) {
-
'キープロパティを上書きしない' をスローします ;
}
- if (
this.sProxy-
=== null) {
-
throw 'sProxy プロパティをオーバーライドしません' ;
}
-
}、
-
-
初期化: function (opts) {
-
this.propertys();
-
this.setOption(opts);
-
this.assert();
-
},
-
-
_getLifeTime: function () {
-
var タイムアウト = 0;
-
var str = this.lifeTime;
-
var unit = str.charAt(str.length - 1);
-
var num = str.substring(0, str.length - 1);
-
var 地図 = {
-
D: 86400,
-
H: 3600、
-
M: 60,
-
S: 1
-
};
-
if (typeof unit == 'string') {
-
ユニットユニット = unit.toUpperCase();
-
}
-
タイムアウト = num;
-
if (unit) timeout = Map[unit];
-
-
//单位は毫秒
-
return num * timeout * 1000 ;
-
}、
-
-
//缓存データ
-
set: 関数 (値, 符号) {
-
//获取过期時間
-
var timeout = new Date();
-
timeout.setTime(timeout.getTime() this._getLifeTime());
-
this.sProxy.set(this.key, value, timeout.getTime(), sign);
-
}、
-
-
//设置单个プロパティ
-
setAttr: function (name, value, sign) {
-
var key, obj;
-
if (_.isObject(name)) {
-
for (名前のキー) {
-
if (name.hasOwnProperty(key)) this.setAttr(k, name[k], value);
-
}
-
戻る;
-
}
-
-
if (!sign) sign = this.getSign();
-
-
//获取当前对象
-
obj = this.get(sign) || {};
-
if (!obj) return;
-
obj[名前] = 値;
-
this.set(obj, sign);
-
-
}、
-
-
getSign: function () {
-
return this.sProxy.getSign(this.key);
-
}、
-
-
削除: function () {
-
this.sProxy.remove(this.key);
-
}、
-
-
removeAttr: function (attrName) {
-
var obj = this.get() || {};
-
if (obj[attrName]) {
-
obj[attrName] を削除します。
-
}
-
this.set(obj);
-
}、
-
-
get: function (sign) {
-
var 結果 = [],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)) {
-
for (var i = 0, len = obj.length; i < len; i ) {
-
結果[i] = obj[i];
-
}
-
} else if (_.isObject(obj)) {
-
結果 = obj;
-
}
-
-
for (a in result) {
-
isEmpty = false;
-
休憩;
-
}
-
return !isEmpty ? 結果: null;
-
}、
-
-
getAttr: function (attrName, tag) {
-
var obj = this.get(tag);
-
var attrVal = null;
-
if (obj) {
-
attrVal = obj[attrName];
-
}
-
return attrVal;
-
}
-
-
});
-
-
Store.getInstance = 関数 () {
-
if (this.instance) {
-
this.instance を返す;
-
} else {
-
return this.instance = new this();
-
}
-
};
-
-
ストアに戻る;
-
});
我们真实使用的時候是使用store这个类操作localstorage,代码结束简单测试:
保存完了、以後ずっと実行要求なし、今日の代コード基本終了、最後に Android ハイブリッド内に後退錉があり、この钮が下に来ると上の 1 つの面に戻り、今度は気候の面のローカルストレージが读取される可能性があります失效! 一つの解決策はウェブアプリに追加されています:
XML/HTML コード复制コンテンツ到剪贴板
-
window.onunload = function () { };//适合单页应用、不要问我は物么、我也不知道
结语
localstorage は移動開墾必需的技术点,深深理解が必要,特定の务代コード後续会が git 上に放り出す,有関心な友友可去知