MENU

TODOアプリを「理解しながら」作る|JavaScriptからVueへの橋渡し

TODOアプリを「理解しながら」作る|JavaScriptからVueへの橋渡し

Vueのチュートリアルを一通り終えたあと、

「動くけど、なぜ動くのかわからない」
「コードは読めるのに、ゼロから書けない」

そんなモヤモヤを感じていませんか?

この記事では、JavaScriptで作ったTODOアプリをVue3で作り直しながら、
Vueの一番大事な考え方である「状態(state)」と「リアクティブ」の正体を、
コードを分解しながら丁寧に解説します。

完成を目指すだけでなく、
「なぜこの書き方になるのか」を理解できることがゴールです。

todoアプリについての解説画像

目次

🎯 あなたのゴール

この記事を読み終えたときに、次の状態になることが目標です。

  • ref.value の意味が説明できる
  • なぜ配列の中身が変わると画面が更新されるのか分かる
  • index の正体が分かる
  • VueがDOM操作を肩代わりしてくれている感覚がつかめる

完成イメージ:Vue版TODOアプリ

  • テキストを入力して「追加」
  • TODOをクリックすると完了 / 未完了が切り替わる
  • 削除ボタンでその行だけ消える
<template>
  <div>
    <input v-model="text" />
    <button @click="addTodo">追加</button>

    <ul>
      <li
        v-for="(todo, index) in todos"
        :key="index"
        :class="{ done: todo.done }"
      >
        <span @click="toggleTodo(index)">
          {{ todo.text }}
        </span>
        <button @click="removeTodo(index)">削除</button>
      </li>
    </ul>
  </div>
</template>

<script setup>
import { ref } from "vue";

const text = ref("");
const todos = ref([]);

const addTodo = () => {
  if (!text.value) return;

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

  text.value = "";
};

const removeTodo = (index) => {
  todos.value.splice(index, 1);
};

const toggleTodo = (index) => {
  todos.value[index].done = !todos.value[index].done;
};
</script>

<style>
.done {
  text-decoration: line-through;
  color: gray;
}
</style>

🧠 Vueで一番大事な考え方:「状態(state)」

まず最初に理解してほしいのがこれです。

JavaScriptだけの場合

const todos = [];

これはただの配列です。


Vueの場合

const todos = ref([]);

これは「Vueに監視されている状態」です。

実は中身はこうなっています。

todos = {
  value: []
}

Vueは
👉 value の中身が変わった瞬間を検知して
👉 画面を自動で更新します


なぜ .value が必要なのか?

Vueの ref は「箱」です。

  • 箱そのもの → todos
  • 中身 → todos.value

だから追加するときはこう書きます。

todos.value.push("買い物");

もし .value を忘れると
👉 Vueは「変化が起きた」と認識できません。


🧩 TODOは「文字」ではなく「オブジェクト」で持つ

最初はこう書きたくなります。

todos.value.push("買い物");

でもこれだと、後で困ります。

  • 完了したか?
  • チェック済みか?
  • 日付は?

👉 情報を追加できない


正解はこちら

todos.value.push({
  text: "買い物",
  done: false
});

これで、

  • text:表示する文字
  • done:完了状態

という状態を持つTODOになります。

これは実務でも必須の考え方です。


✏️ addTodo を1行ずつ解説

const addTodo = () => {

「追加ボタンを押したときに実行される関数」


if (!text.value) return;

意味は👇

  • 入力欄が空なら
  • 何もせず終了

省略しないとこうです。

if (text.value === "") {
  return;
}

todos.value.push({
  text: text.value,
  done: false
});
  • todos配列に
  • 新しいTODOオブジェクトを追加

text.value = "";

入力欄を空に戻して、使いやすくしています。


🔁 v-for の index の正体

<li v-for="(todo, index) in todos">

これはJavaScriptでいうとこうです。

todos.forEach((todo, index) => {
  // todo → 中身
  // index → 番号
});

例:

indextodo
0{ text: “買い物”, done: false }
1{ text: “掃除”, done: true }

🗑 削除処理で使っている index

const removeTodo = (index) => {
  todos.value.splice(index, 1);
};

splice の意味

splice(消す位置, 消す個数)

例:

["A", "B", "C"].splice(1, 1);
// → ["A", "C"]

👉 押した行だけ消える理由はこれです。


✅ 完了状態の切り替え(トグル)

todos.value[index].done = !todos.value[index].done;

これはON / OFFの切り替え。(スイッチみたいな感覚)

分解するとこうです。

if (todos.value[index].done === true) {
  todos.value[index].done = false;
} else {
  todos.value[index].done = true;
}

🎨 class の切り替えはVueがやってくれる

:class="{ done: todo.done }"

これは裏側では、こんなことをしています。

if (todo.done) {
  li.classList.add("done");
} else {
  li.classList.remove("done");
}

👉 DOM操作をVueが代行してくれている。

まとめ

ここまで理解できると、

  • JavaScriptの配列・オブジェクトを理解している。
  • Vueのリアクティブの正体がわかる。
  • indexを使った操作ができるようになる。
  • 「なぜこのコードなのか」を説明できるようになる。

引き続きVueの理解を一緒に深めていきましょう!!^^

その他関連記事はこちら→プログラミング備忘録

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

初心者の私がコーディングをしていて躓いたところをピックアップして日々の備忘録として発信しています^^
楽しくコーディングを身に着けていけるように日々勉強中です★

コメント

コメントする

目次