スマートフォンサイトでlocalStorageを使ってみたので、これからも幸せなlocalStorageライフを送る為に覚え書き。
localStorageとは
一言で言うと、「いろいろなデータをクライアント側に保存するKVS」です。このKVSというのは「Key-Value Store」の事で、データを、ユニークなKey(識別子)とValue(値)のペアで保存する方式のことです。
team_k001 = 大島優子,
team_k002 = 板野友美,
team_b001 = 小嶋陽菜
というように、key = valueのペアにして、このペアとなったデータをクライアント側に保存してしまおうというわけですね。この技術の事を「Web Storage」と呼び、W3Cで策定が進められています。Web Storageの実体は、2種類のオブジェクトにより構成されていて、そのひとつが「localStorage」で、もうひとつは「sessionStorage」です。 詳しい仕様についてなどは下記を。
それどう使うの?
現在のナウでヤングなWebサイトでは、何らかの「情報」とか「状態」などを管理をする必要があります。例えば、このユーザーは一覧ページのソート順は「値段の安い」順にしたから次回表示する時も値段の安い順にするとか、ユーザーのログイン状態はどうなってる?とか、そういうのですね。これまではCookieなどを使って実現していた「何かを保存しておいて後で使う」みたいな事を実現する次世代技術として注目されています。
Cookieよりも安全かつ大容量で有効期限もありません。その気になれば画像であっても保存可能です。
ただし、パフォーマンスの問題などもあるようなので、「うはwwwlocalStorage楽過ぎwww全部これでよくね?wwww」ではなく、使いどころは慎重に考えた方が良さそうです。
環境による制限などももちろんある
当然ですが、どの環境でも使えるわけではないので、そのあたりも考慮が必要ですね。IE6,7が対応しているかどうかなんて野暮な事聞く人はいないと思いますが、安定の未対応ですのでご安心ください。IEは8から使えるようですね。Android、iOSなど、スマートフォン環境であれば基本的にlocalStorageは動くようなので、スマホ・タブレット向けサイトであれば、あまりあれこれ考えずに使えるんじゃないでしょうか。
また、データはオリジン毎に保存されます。オリジンとは、プロトコル、ドメイン、ポート番号の事で、例えば、「http://example.com/」で保存したデータは、「http://example.com/」じゃないと読み書きできないです。
httpsになってもアウト、サブドメインが付いてもアウト、ポート番号が変わってもアウト(通常は80なのであまり考えなくて良いと思うけど)ですよという事です。
もちろん、「http://www.example.com/」のwwwの有無もサブドメインですから当然区別されます。
localStorageを使った何らかの機能を作るだけ作って、データ読み書きできなくて「\(^o^)/」などにならないように注意してください。
ただ、その気になればドメインの制限を突破してクロスドメインで使う事もできるみたいです。
とにかく使ってみる
基本的には、保存、取得、削除のみです。ものすごく簡単です。
とにかく使ってみる
//localStrage.setItem("key","value");
localStorage.setItem("team_k001","大島優子");
//プロパティ・ハッシュアクセスもできる
localStorage.team_k001 = "大島優子";
localStorage["team_k001"] = "大島優子";
//localStrage.getItem("key");
localStorage.getItem("team_k001"); //"大島優子"
//プロパティ・ハッシュアクセスもできる
localStorage.team_k001; //"大島優子"
localStorage["team_k001"]; //"大島優子"
以上。早。
※保存/取得時の注意点として、プロパティ、ハッシュアクセスはなるべく使用せず、setItemやgetItemなどのメソッドを使う事が推奨されてます。プロパティ、ハッシュアクセスだと、ブラウザ毎に挙動が違ってアレらしいです。
注: 通常のJavaScriptのプロパティアクセスメソッド経由で値を読み書きできますが、getItem および setItem メソッドの使用が推奨されています。 DOM Storageリファレンス
保存するデータについて
上記のように書くだけで簡単にデータが格納できるんですが、この世に人間として生まれたからには当然下記のようにしたいという欲求が生まれます。
var obj = {
data01:"hoge",
deta02:"fuga"
};
localStorage.setItem("testData",obj);
上記は一例ですが、ようするにオブジェクトなりなんなりの「データの塊」をlocalStorageに保存したくなるんですね。オブジェクトごと突っ込んで、これでCoolなlocalStorageライフが送れるゼ!って思ってたんです。
ところがですね、データの取得を行うと、とんでもない事が起こるわけですよ。
//データの取得
localStorage.getItem("testData");
//期待する結果
Object { data01="hoge", deta02="fuga"}
//実際に返って来る結果
"[object Object]"
そうですね、”[object Object]”ですね。うん。それはわかりますよ。なにせ格納したのはobjectですからね。そう、何度コンソールを実行しても、いつだって返ってくるのは”[object Object]”なんですよ。
実はこれ、文字列がそのまま返ってくるんですね。これには口に含んだコーヒーを吹き出しそうになりましたが、そこは冷静にドキュメントを参照します。
注: このページで説明しているどの Storage も、それにストアするものはすべてその .toString メソッドによって文字列に変換されてからストアされるということを念頭に置いてください。ですから、普通のオブジェクトをストアしようとすれば、そのオブジェクトやJSON表現がストアされるのではなく、”[object Object]”という文字列となります。オブジェクトを文字列形式にするには、ブラウザが提供するJSONのパース、文字列化のネイティブなメソッドを使うのが、普通で有効な方法でしょう。 DOM Storageリファレンス
はい、念頭に置けてませんでした。 なるほど、保存する前に.toString()してるんですね。期待する結果を得る為の解決方法も書いてあります。
var obj = {
data01:"hoge",
deta02:"fuga"
};
//データの保存
localStorage.setItem("testData",JSON.stringify(obj));
//データの取得
JSON.parse(localStorage.getItem("testData"));
JavascriptオブジェクトをJSON文字列に変換する為に、JSON.stringifyしながらsetItemします。
データの取得時は、JSON文字列をJavascriptオブジェクトに変換する為に、JSON.parseしながらgetItemすれば良いわけですね。
セキュリティの問題とかがクリアになるならevalとかでもなんとかなるんじゃないですかね。とにかく、これでオブジェクトを格納できるので、データによっては扱い易くなるんじゃないかと思います。
とにかく使ってみる -データ削除-
次はデータの削除。removeItemメソッドで削除したいkeyを指定。
//データの保存
localStorage.setItem("data1","hoge");
localStorage.setItem("data2","fuga");
//データの削除
localStorage.removeItem("data1");
//確認
localStorage.getItem("data1"); //undefined
localStorage.getItem("data2"); //"fuga"
次、全削除。ドメイン単位のデータを全て消します。いわゆるバルス。
//データの保存
localStorage.setItem("data1","hoge");
localStorage.setItem("data2","fuga");
//バルス
localStorage.clear();
//確認
localStorage.getItem("data1"); //undefined
localStorage.getItem("data2"); //undefined
全削除は、そのドメインで保存している全てのデータが削除されます。意図している場合ならいいですが、もし間違ってバルスしちゃうと全てが終わるので注意が必要です。
とにかく使ってみる -データ取得その他-
indexを指定してデータの取得もできる。
//データの保存
localStorage.setItem("data1","hoge");
localStorage.setItem("data2","fuga");
//indexを指定してデータを取得
localStorage.key(0); //"hoge"
もちろんlengthも取得できる。
//データの保存
localStorage.setItem("data1","hoge");
localStorage.setItem("data2","fuga");
//lengthを取得
localStorage.length; //2
localStorageに保存されている全てのkeyを取得してみる。
//データの保存
localStorage.setItem("data1","hoge");
localStorage.setItem("data2","fuga");
for(var i = 0; i < localStorage.length; i++){
console.log(localStorage.key(i));
}
//結果
data1
data2
localStorageに保存されている全ての値を取得してみる。
//データの保存
localStorage.setItem("data1","hoge");
localStorage.setItem("data2","fuga");
for(var i = 0; i < localStorage.length; i++){
var k = localStorage.key(i);
console.log(localStorage.getItem(k));
}
//結果
hoge
fuga
だいたいこんな感じですかね。あとは、Storageイベントなんてのもあります。storage内のデータが変更されたりすると、それを補足して何かするって事が可能です。
ただし、storageイベントを監視して何か変更があっても、変更元のタブでは何も起こらないです。変更元以外のタブでイベントが発火します。
使いどころとしては、複数のタブで同じドメインのサイトを開いていたりする場合、今見ているタブでlocalStorageに何らかの変更が加えられたら、開いてある他タブの同ドメインサイトの状態と不整合が起こるので、他タブの更新処理をかける。とかそんな感じでしょうか。
//storageイベントを監視
window.addEventListener("storage",function(e){
//何か処理
},false);
いろいろ使いどころはありそうですね。storageイベントオブジェクトのプロパティ一覧はここらへんを。
最近チェックしたアイテムを作った
で、実際にこのWebStorageを使って何をしたかということなんですが、最近チェックしたアイテムという機能を実装しました。
僕はECサイトを管理・運用しているわけですが、ECサイトには、ほぼ必ず実装されているであろう「最近チェックしたアイテム」という機能があります。
アイテム詳細ページなんかをユーザーが閲覧すると、Web側で閲覧したアイテムを覚えておいて、サイドバーとかで最新何件とかを表示するアレですね。
もちろん機能としては既にあるものなのですが、諸事情でいろいろな制約があり、機能的にちょっと貧弱だったので、データの保存・取得元をlocalStorageで実現しようという欲求を抱いたのでスマホサイトに実装しました。
ただ、この機能に関しては、あえてlocalStorageを使う必要があるかどうかは微妙ですね。別にCookieでいいし。
メリットをあげるとすれば、トラフィックの削減にはなってますね。Cookieは毎回サーバーとやりとりするのでもちろん通信が発生しますが、localStorageはその必要がないので。
WebStorageの使い道
ユーザーがそのWebサイトでどういった設定をしたのか保持しておいて、次回訪問時に活用するという機能をもったサイトは珍しくないと思いますが、上でも書いたように、何かの一覧のソート順とか、複数ある表示レイアウトからユーザーが選んだ表示形式が次回訪問時ではデフォルトになっているとか。
などなど、次に同じユーザーが来たときもその設定になってると便利だよねみたいなものをユーザー毎(と、言うかブラウザ毎)に保持しておくとかいいんじゃないですかね。
まぁこれも別にCookieでもいいんだけど、Cookieでは実現できなかった大きめのデータを格納することもできますし。
あとは、レスポンス改善に貢献するような使い方ですかね。プリフェッチ(データ先読み)とかスマホサイトとかで良さそうですね。
ただ、このデータは俺の生きた証だとか、あのデータが無くなると世界が滅亡するみたいなデータを突っ込んで、それが復元可能ならまだいいんですが、localStorageだけが最後の砦みたいな使い方すると、もしブラウザでクリアされちゃったら誰かが死ぬかもしれないので避けたほうが無難だと思いますよ。
以上、基本的な事ばかりですが。
コメント
コメント一覧 (1件)
参考になりました、ありがとうございます。
※一部「localStrage」になっており悩みました。(→「localStorage」)