- 公開日: 2018年05月24日
localStorageでWebアプリのデータを保存する
Webアプリ開発では、「データの保存」を行う必要が出てくる場面も多いと思います。クラウド的な発想では、会員登録をしてもらってサーバーに保存、という形になるわけですが、サーバーの開発や会員管理ができない、ユーザー側に保存しておきたい、ということもありますね。 そんな時に便利なのが、Webブラウザにデータを保存するlocalStorageです。
localStorageとは
localStorageは、Webブラウザが管理するデータの保存領域です。
データの名前とデータ文字列をlocalStorageに渡すとデータが保存され、一度保存したデータは名前で呼び出すことができます。名前(キー)に紐づけて値を保存するkey-value型のデータ構造になっているわけですね。
保存できる容量はWebブラウザ次第ですが、5MB程度は保存できるようになっているので、ある程度の大きさの画像データを扱うこともできるでしょう。
ただ、localStorageに保存したデータを読み込めるのは、データを保存したサイト(ドメインに加えhttp/httpsといったプロトコルやポートも同じ同一オリジン)のみに限定されています。
たとえば、
で保存したデータは
でも読み込むことができますが
では読み込めません。
オリジン単位でデータを管理することで、データ漏洩や名前の衝突といった問題を軽減する仕組みになっています。
ただし、同一オリジン内で多数のユーザーが(ディレクトリ別などの形で)住み分けそれぞれコンテンツを公開する形のサイトでは、他のユーザーにデータが漏洩したり名前が衝突する可能性があるため、十分な注意が必要です(後で見るように、名前を特定できなくてもデータの取得は可能)。
localStorageの読み書き
localStorageへのデータ保存と読み出しは、setItem()/getItem()で行います。
localStorage.setItem(名前, データ文字列);
とすると指定の名前で文字列がlocalStorageに保存され、保存された文字列は
localStorage.getItem(名前)
で読み出すことができます。
以下のHTMLファイルを作成し、Firefoxで開いてみてください(Webブラウザによってはローカル実行時にlocalStorageの機能が無効化/制限されます)。
このHTMLファイルには、「setボタンでlocalStorageにtestという名前で文字列データ"aaa"を保存し、getボタンでlocalStorageのtestを読み出して表示する」JavaScriptのコードが埋め込まれています。
<!DOCTYPE html>
<html>
<body>
<script>
function set() {
localStorage.setItem("test", "aaa");
}
function get() {
alert(localStorage.getItem("test"));
}
</script>
<button onclick="set()">set</button>
<button onclick="get()">get</button>
</body>
</html>
Webブラウザで開いた直後にgetボタンをクリックすると、nullまたはundefinedと表示されたと思います。localStorageにデータを入れてないので、当然ですね。
次にsetボタンをクリックして、クリック時に呼び出されるset()内の
localStorage.setItem("test", "aaa");
を実行しましょう。
これで、localStorageのtestにaaaという文字列が保存されました。
再びgetボタンをクリックしてlocalStorage.getItem("test")を表示させてみると……今度は、先ほど保存したaaaという文字列が表示されるはずです。
localStorageへの保存と読み出しは、JavaScriptの配列と同じ感覚で行うこともできます。
この場合は、
localStorage[名前] = データ;
とするとデータが保存され、
var data = localStorage[名前];
のようにデータを読み出すことができます。
localStorageのデータ管理
localStorageの基本的な読み書きができたので、続いてデータの削除や確認といった管理を試してみましょう。
まず、名前を指定して記録したデータを削除するにはremoveItem()を呼び出します。
localStrorage.removeItem(名前);
とすると、指定された名前で登録されているデータが削除されます。
setItem()/getItem()/removeItem()の動作を確認するHTMLファイルを作ってみたので、Webブラウザで試してみてください。
<!DOCTYPE html>
<html>
<body>
<script>
function set() {
localStorage.setItem("test", "aaa");
}
function get() {
alert(localStorage.getItem("test"));
}
function remove() {
localStorage.removeItem("test");
}
</script>
<button onclick="set()">set</button>
<button onclick="get()">get</button>
<button onclick="remove()">remove</button>
</body>
</html>
今回は、データを削除するremoveボタンを追加してみました。クリックすると、testの名で登録されているデータを削除(removeItem())します。
まず、set/getボタンでデータを読み出せることを確認してから、removeボタンをクリックしてください。続いてgetボタンをクリックすると、今度はデータが削除されているためnullと表示されるはずです。
removeItem()で名前を指定してデータを削除する以外に、clear()で(同一オリジンで登録した)すべてのデータを削除することも可能です。ただ、他のページで使っているデータまでまとめて削除されることになるので、注意してください。
続いて、localStorageに現在登録されているデータを確認する方法を見てみましょう。
localStorageに登録されているデータ数は、lengthプロパティで取得できます。localStorageには、登録されているデータの名前をデータの番号で取得するkey()があるので、lengthでデータの個数を取得すると、「localStorageに保存されている全データの名前と値」を以下のように列挙することができます。
for (var i = 0;i < localStorage.length;i++) {
var key = localStorage.key(i);
var value = localStorage.getItem(key);
}
これまで見てきたデータの登録と削除、列挙を試すHTMLファイルを作りましたので、Webブラウザで開いてみてください。
<!DOCTYPE html>
<html>
<body>
<script>
function set() {
var key = document.getElementById("key_field").value;
var value = document.getElementById("value_field").value;
localStorage.setItem(key, value);
}
function get() {
var key = document.getElementById("key_field").value;
alert(localStorage.getItem(key));
}
function remove() {
var key = document.getElementById("key_field").value;
localStorage.removeItem(key);
}
function data_list() {
var text = "";
for (var i = 0;i < localStorage.length;i++) {
var key = localStorage.key(i);
var value = localStorage.getItem(key);
text += key + ":" + value + "\n";
}
alert(text);
}
</script>
<p>
key:<input id="key_field">
value:<input id="value_field">
</p>
<p>
<button onclick="set()">set</button>
<button onclick="get()">get</button>
<button onclick="remove()">remove</button>
<button onclick="data_list()">data_list</button>
</p>
</body>
</html>
keyとvalueという入力欄がありますが、これはそれぞれデータの名前と値を指定するものです。
keyとvalueに適当な文字列を入れてsetボタンをクリックすると、その名前と値でデータを記録します。また、keyに文字列を入れてget/removeボタンをクリックすると、keyの名前でデータの表示と削除を行います。
data_listボタンをクリックすると、現在localStorageに登録されているデータを「名前:値」の形で列挙します。
いくつかデータを登録してから、data_listボタンをクリックしてみてください。
\Webサイト担当者としてのスキルが身に付く/
localStorageにバイナリ(画像)データを保存する
localStorageに保存できるデータは文字列なので、これまでは単純な文字列を保存してきましたが、バイナリデータも文字列化すればlocalStorageに保存することができます。
canvas要素やimg要素では、その文字列化されたバイナリ(Base64形式のDataURL)を扱うことができるので、試してみましょう。
以下のHTMLファイルは、256*256ピクセルのcanvas要素を配置し、drawボタンをクリックすると、適当な長方形を描くようになっています。
setボタンでlocalStorageに現在のcanvas要素の画像を保存し、getボタンでlocalStorageのデータをImageオブジェクトに読み込みcanvas要素に描くようにしてみました。
<!DOCTYPE html>
<html>
<body onload="init()">
<canvas id="draw_canvas" width="256" height="256" style="width: 256px; height: 256px;"></canvas>
<script>
function draw() {
var cv = document.getElementById('draw_canvas');
var context = cv.getContext('2d');
context.fillStyle = '#ff8000';
var x = Math.random() * 128;
var y = Math.random() * 128;
var w = Math.random() * 128;
var h = Math.random() * 128;
context.fillRect(x, y, w, h);
}
function set() {
var cv = document.getElementById('draw_canvas');
var context = cv.getContext('2d');
var data = cv.toDataURL();
localStorage.setItem("draw_data", data);
}
function get() {
var data = localStorage.getItem('draw_data');
var img = new Image();
img.onload = view;
img.src = data;
}
function view(e) {
var img = e.target;
var cv = document.getElementById('draw_canvas');
var context = cv.getContext('2d');
context.drawImage(img, 0, 0);
}
function init() {
var cv = document.getElementById('draw_canvas');
var context = cv.getContext('2d');
context.fillStyle = '#e0e0e0';
context.fillRect(0, 0, 256, 256);
}
</script>
<p>
<button onclick="draw()">draw</button>
<button onclick="set()">set</button>
<button onclick="get()">get</button>
</p>
</body>
</html>
localStorageにcanvas要素の画像を保存する処理は、以下のようになっています。
function set() {
var cv = document.getElementById('draw_canvas');
var context = cv.getContext('2d');
var data = cv.toDataURL();
localStorage.setItem("draw_data", data);
}
このコードでは、cvanvas要素から取得したcontextのtoDataURL()で文字列化した画像データ(png形式)を取得し、localStorageにdraw_dataの名前で保存しています。
バイナリデータを文字列化すると多少サイズが膨らむこともあって、画像データはかなり大きくなりますが、この程度の大きさであれば問題ないでしょう。
get()の読み出し時には、まずImageオブジェクトのsrcにlocalStorageから読み込んだデータを設定して画像を作成、続いてcanvasから取得したcontextのdrawImage()で描画しています。
なお、このHTMLで画像を保存すると極めて長い文字列がlocalStorageに保存されることになるので、画像を保存した状態で先に試したデータ一覧を実行する際は注意してください(パソコン版Firefoxでは大丈夫のようですが、Webブラウザによっては問題が生じるかもしれません)。
- この記事を書いた人
- 宍戸輝光