WebStorageで一時データ管理をする

#はじめに
クリスマスイブの妖精、大林雄一郎です。

もともとDartsLive200Sというおもちゃで練習用アプリをつくる予定だったんですが
自宅にある本体が壊れて端末に接続できない致命的な障害が発生したので買い直してまた次回のネタにします。

なので今回は即席感満載ですがWebStorageのお話です。

# WebStorageとは
ググれば記事たくさんあるんですが
ローカル環境（ブラウザ）にデータをKeyValueで保存するための仕組みです。
データの編集や保存がJavaScriptでできるようになります。

今回はWebアプリで画面操作後の編集データをDB更新前まで保持して、都度画面表示に使用したいといった仕様で使いました。

###WebStorageについて
これもググれば記事たくさんあるので省略しますが、簡単に書くと以下の種類と特徴があります。

■SessionStorage
　・ブラウザ、タブ閉じるまで保存したデータを保持。
　・Keyが同じでもブラウザ、タブ間では別データとして扱う。
　・sessionて名前だけどサーバは関与しない。
　　⇒session生成元ごとに区切られた保存領域を使用している。らしい。

■LocalStorage
　・任意に消すまで保存したデータを保持。
　・Keyが同じである場合ブラウザ、タブ間では共通のデータとして扱う。
　・ローカルマシンの領域にデータが保持される。

###WebStorageいいこととわるいこと
■いいこと
・クライアントでデータ管理が完結する（サーバいらない）
・最近のブラウザであればなんでも使用可能
・jsなので開発者ツールでデータの状態が把握しやすい

■わるいいこと
・jsなのでXSS対策していないと危険
　⇒個人情報や機密情報は保持しちゃだめ
・Localの場合、明示的に破棄しなければデータが残る
　⇒管理はちゃんとしなきゃだめ

#使用例～画面仕様～
↓みたいな画面で
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215570/42cbb722-9242-6699-3932-181b6f81bb33.png)

緑枠GRIDのデータは行毎に↓みたいな子画面で登録
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215570/90c5b7a1-aa09-6612-07ce-996d5db4d79e.png)

子画面での登録時に、緑枠GRIDに値を反映させる、といった画面挙動をします。
ただし子画面での登録ではDBへの反映はさせず、親画面の更新ボタンで一括でDBへ反映させるという仕様。

今回は以下の観点からSessionStorageを選択しています。
　①運用上ブラウザで複数タブ開いて複数データを同時に参照する
　②画面表示だけに使用できればよい

#使用例～実装～
WebStorageメソッド・属性定義用js
getItem、setItem、removeItemくらいですかね使うの。

コードの冒頭でやっていますがuseSessionや
var storage = sessionStorage（localStorage）
にてsession or localの指定を行います。

```js
var SaenaiWebStorage = {
	
	useSession: true,		// セッションストレージを使うか否か

	/**
	 * Storageが使用可能かどうか
	 */
	usable : function () {
		return (typeof localStorage !== 'undefined');
	},

	/**
	 * ストレージを取得する
	 *
	 */
	getStorage : function (useSession) {
		return (useSession) ? sessionStorage : localStorage;
	},

	/**
	 * 保存する
	 *
	 * @param key
	 * 				Key名
	 * @param data
	 * 				データ
	 */
	save : function (key, data) {
		SaenaiWebStorage.getStorage(this.useSession).setItem(key, JSON.stringify(data));
	},

	/**
	 * 取得する
	 *
	 * @param key
	 * 				Key名
	 */
	get : function (key) {
		var data = SaenaiWebStorage.getStorage(this.useSession).getItem(key);
		return (data == null) ? null : JSON.parse(data);
	},

	/**
	 * 削除する
	 *
	 * @param key
	 * 				Key名
	 */
	remove : function (key) {
		SaenaiWebStorage.getStorage(this.useSession).removeItem(key);
	},
		
	/**
	 * 全てクリアする
	 *
	 */
	clear : function () {
		SaenaiWebStorage.getStorage(this.useSession).clear();
	}
}
```



画面別の保持データモデル
dataの内容がデータ保持対象の項目です。
functionは画面仕様に沿うことになり、data取得など個別の実装をしていくことになりますが、
基本的には↑のWebStorageメソッドを使用するものが最低限必要だと思います。

```js
/**
 *×× データリポジトリ
 *
 * WebStorageに中間データを保持する
 *
 */
var SaenaiRepository = {

    keyName : 'Blessing',

    data: {
        SaenaiKishList: [],                 //冴えない会社リスト
        CircleNameList: [],                 // サークル名リスト
        combobox: [],                       // 名称表示用Combobox
        shinkanInfo: null                   // 高くて薄い本情報
    },

    restore: function() {
        var storageData = SaenaiWebStorage.get(this.keyName);
        if (storageData != null) {
            this.data = storageData;
        }
    },
    save: function() {
        SaenaiWebStorage.save(this.keyName, this.data);
    },
    isRestored : function() {
        return this.data.SaenaiKishList.length > 0;
    },
    initialize : function () {
        this.restore();
    },
    remove: function() {
        SaenaiWebStorage.remove(this.keyName);
        this.data = {
            SaenaiKishList: [],
            CircleNameList: [],
            combobox: [],
            shinkanInfo: null
        }
    },
    getCircleName : function(cd) {
        var item = getItemfromList(this.data.CircleNameList, 'xxxxx', cd);
        return item == null ? '': item.yyyyyy + '：' + item.zzzzzz;
    },
    getSaenaiSikyKish: function (sikyKishKbn) {
        return getItemfromList(this.data.SaenaiKishList, 'kishKbn', kishKbn);
    },
    getComboboxItem: function (comboboxName, valueFieldName, value) {
        var list = this.data.combobox[comboboxName];
        return getItemfromList(list || [], valueFieldName, value);
    },
    getshinkanInfo: function(){
        return this.data.shinkanInfo;
    }
}

```

あとは画面でsaveしたい、removeしたい、getしたい場合のイベントでこれらを呼ぶだけで一時データ管理ができます。

#最後に
大昔に同じような仕様でわざわざDBにGRID編集用のワークテーブルを作った黒歴史があったので
今回同じ過ちを繰り返すことがなくて本当によかったです（小並
他にもWebStorageの使いどころって何があるか考えてみようと思いました。


さーて素敵なイブのはじまりだﾈ☆