ふみぽん's diary

技術的な備忘録が主のブログ

【JavaScript】Storage(ストレージ)について 『+ todoアプリ』

JavaScript】Storage(ストレージ)の勉強


JavaScriptでストレージ操作

Web Storage(ストレージ)

JavaScriptの世界では、書いたスクリプトからコンピューターに勝手に書き込むことは許容されるべきではないという考えのようです。 例えば、buttonをクリックしたらコンピューター内のファイルを書き換えてしまうようのことがあるべきではないということ。

ただ、例外が、、、

例外となる手段として、「クッキー(cookie)」という仕組みです。
Webアプリケーションで、クッキーを利用することでクライアントに対して文字列を保存することができるようになります。

でも、このクッキーはJavaScriptでは操作しにくいようです (クッキーについては、次回調べてみようと思います。本当はクッキーを使ってコード書く予定でした。。。)

では、クッキーの代替技術は?

それが、Web Strage(ストレージ)です!
ストレージとは、ブラウザ内臓のデータ保管庫のことです。
ストレージには、データと特定するためのkeyと値valueの組み合わせで保存します。

key value
color1 あか
color2 ピンク
... ...

ローカルストレージとセッションストレージ

ストレージは、ローカルストレージセッションストレージに分類されます。
以下で、両者の違いを見ていきます。

ローカルストレージ
  • オリジン単位でデータを保管
  • ブラウザを閉じてもデータがストレージから消滅しない
ちなみに、「オリジン」とは
【http://www.xyz:8080/」のように「スキーマ://ホスト名:ポート番号」の組み合わせで表せる単位のこと
セッションストレージ
  • セッション(ブラウザを開いている間)で維持されるデータを管理
  • ブラウザを閉じるとデータがストレージから消滅する

では、どのように使い分ける?

結論としては、
セッションストレージでまかなえるのであれば、優先して利用するべき

その理由としては、 ローカルストレージには、以下のようなデメリットがある。  

  • 明示的にデータを削除しない限り、データが消えない  

=> ゴミがたまる変数名が被ったりすると予期せぬ動きになる


データ保存/取得方法

記法 コード
プロパティ構文 strage.キー名
ブラケット構文 strage['キー名']
メソッド構文(取得) strage.getItem('キー名')
メソッド構文(保存) strage.setItem('キー名', '値')

保存について - ストレージに保存できる値の方は文字列

オブジェクトを保存するには - 復元可能な文字列に変換してから保存する

以下、変換及び復元のサンプルコード

const toString = () => {
  const obj1 = {
    name: "xxx",
    price :2300,
  }
  console.log(obj1); // => オブジェクトとして出力

  //オブジェクト→文字列(変換)
  const str = JSON.stringify(obj1);
  console.log(str); // => 文字列として出力

  //文字列→オブジェクト(復元)
  const obj2 = JSON.parse(str);
  console.log(obj2); // => オブジェクトとして出力
}

サンプルコード

ストレージを使ってtodoリストのアプリケーションを作りましたので、
スクリプトファイルを載せておきます。

//ストレージへのアクセスのために、Strageオブジェクトを変数に格納
let strage = localStorage;    //=> ローカルストレージの場合
// let strage = sessionStorage; => セッションストレージの場合


//キーを指定してストレージに保存している値を取得
let todoTasks = strage.getItem("todoTasks");

if(todoTasks !== null){
  //ストレージに保管されていた文字列からオブジェクトを復元
  todoTasks = JSON.parse(todoTasks);
} else {
  todoTasks = [];
}

const todoForm = document.getElementById("todo_form");
const todoList = document.getElementById("todo_list");

const todoInput = document.querySelector("#todo_form input");

const addItem = (event) => {
  //formによる画面遷移を止める
  event.preventDefault();

    const taskString = todoInput.value;
  if(taskString.length === 0){
    alert("やること入力して");
    return;
  }

  todoTasks.push({
    text: todoInput.value,
    done: false,
  });

  render();
  todoInput.value = "";
}

const render = () => {
  todoList.innerHTML = "";

  console.log(todoTasks);

  todoTasks.forEach(function(task) {
    //未完了・完了を管理するチェックボックス
    const checkBox = document.createElement("input");
    checkBox.type = "checkbox";
    checkBox.checked = task.done;
    checkBox.addEventListener("click", function(event){
      task.done = event.target.checked;
    });

    //追加されたタスクを表示するため
    const span = document.createElement("span");
    span.textContent = task.text;

    //テキストをクリックしてもチェックされるようにラベルの子要素とする
    const label = document.createElement("label");
    label.appendChild(checkBox);
    label.appendChild(span);

    //削除ボタン
    const deleteButton = document.createElement("button");
    deleteButton.textContent = "削除";
    deleteButton.addEventListener("click",function() {
      const index = todoTasks.indexOf(task);
      if(0 <= index){
        todoTasks.splice(index,1);
      }
      render();
    });

    const taskList = document.createElement("li");
    taskList.appendChild(label);
    taskList.appendChild(deleteButton);

    todoList.appendChild(taskList);
  });
  //オブジェクトを文字列に変換してからストレージに保存する
  strage.setItem("todoTasks" , JSON.stringify(todoTasks));
};

todoForm.addEventListener("submit",addItem);

render();