MENU

【Vue3入門】TODOアプリで理解するcomputedと表示切り替え|DOM操作しない理由を解説

🔰 Vue3入門|TODOアプリで学ぶ「表示切り替え」と自動更新の仕組み

Vueの基本文法を一通り学んだあと、こんな壁にぶつかる人は多いです。

  • ボタンを押したら表示が変わる仕組みがよく分からない
  • DOMを触っていないのに、なぜ画面が更新されるのか不思議
  • computed が何をしているのか曖昧

この記事では、TODOアプリを題材にしながら
Vueがどのように「状態 → 表示」を自動でつないでいるのかを、できるだけ噛み砕いて解説します。


computedについての解説画像
TOC

🎯 この記事のゴール

この記事を読み終えたときに、次のことが理解できていればOKです。

  • 「表示の切り替え」はDOM操作ではなく状態管理で行う
  • computed は「表示専用の自動計算結果」である
  • Vueは「データが変わったら画面を作り直す」仕組みを持っている

完成イメージ

  • TODOを追加できる
  • TODOをクリックすると完了/未完了を切り替えられる
  • 「すべて / 未完了 / 完了」で表示を切り替えられる

使用するVueの書き方について

この記事では Vue3の最新スタイルを使います。

  • Composition API
  • <script setup>
  • ref / computed

全体の完成コード(Vue3)

template

<template>
  <div class="todo-app">
    <h2>TODOリスト</h2>

    <!-- 追加エリア -->
    <div>
      <input v-model="text" placeholder="やることを入力" />
      <button @click="addTodo">追加</button>
    </div>

    <!-- 表示切り替え -->
    <div class="filters">
      <button @click="filter = 'all'">すべて</button>
      <button @click="filter = 'active'">未完了</button>
      <button @click="filter = 'done'">完了</button>
    </div>

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

script(Composition API)

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

// 入力欄
const text = ref("");

// TODOの元データ
const todos = ref([]);

// 表示モード
const filter = ref("all");

// 追加
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;
};

// 表示用の配列(自動計算)
const filteredTodos = computed(() => {
  if (filter.value === "active") {
    return todos.value.filter(todo => !todo.done);
  }

  if (filter.value === "done") {
    return todos.value.filter(todo => todo.done);
  }

  return todos.value;
});
</script>

style(最低限)

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

🧠 仕組みを順番に理解する

① 表示を切り替える正体は「状態」

const filter = ref("all");

この変数は、

  • 今「どれを表示したいか」を記録するためのもの
  • 画面を直接操作しているわけではない

ボタンを押すと、ただ filter の中身が変わるだけです。

<button @click="filter = 'active'">未完了</button>

② 表示用の配列を作る computed

const filteredTodos = computed(() => {
  if (filter.value === "active") {
    return todos.value.filter(todo => !todo.done);
  }
  if (filter.value === "done") {
    return todos.value.filter(todo => todo.done);
  }
  return todos.value;
});

これは日本語にするとこうです。


filter と todos を見て
今表示すべき配列を返す

ポイント

  • 自分で呼ばない
  • 自分で更新しない
  • 元データ(todos)は壊さない

👉 表示専用のコピー


③ 表示は v-for に任せる

<li v-for="(todo, index) in filteredTodos">
  • 並べているのは filteredTodos
  • todos を直接操作していない

これが 状態と表示を分ける設計です。


④ DOM操作をしていないのに動く理由

このアプリでは、

  • document.querySelector
  • textContent
  • classList

を一切使っていません。

代わりにやっているのは、

  • 状態(ref)を変更
  • Vueが自動で再描画

👉 Vueは
「データが変わったら、画面を作り直す」
というルールで動いています。


🎯 ここまで理解できたらOK

次のことが説明できれば、Vueの基礎はしっかり身についています。

  • 表示切り替えは DOM ではなく 状態で行っている
  • computed は「自動で作られる表示用データ」
  • template は「状態をどう見せるか」だけを書く

その他関連記事はこちら→Programming Notes

Let's share this post !

Author of this article

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

Comments

To comment

TOC