3分でできるVue 3のTodoリストアプリの作成手順

Vue.jsの作業環境を作成

作業前には以下のコマンドを実行してVue.jsの作業環境を作成してください。

Node.jsを使用しているため、インストールしていなければ事前に入れてください。

npm create vite@latest vue-todo -- --template vue

CSSは使わないのでmain.jsの「import './style.css'」は削除してください。

Todoリストアプリの作成手順

1. 雛形のHTMLを作成

まずApp.vueに雛形となるHTMLを記述します。

今回はinputタグに入力して追加ボタンを押すとulタグ内に追加されるものとします。

追加されたものにはXボタンが付いていてXを押すと削除されます。

<template>
  <form>
    <input>
    <button>追加</button>
  </form>
  <ul>
    <li>foo <button>X</button></li>
    <li>bar <button>X</button></li>
    <li>baz <button>X</button></li>
  </ul>
</template>

2. Vueのrefをimport

templateタグの上にscriptタグをimportします。

「newTodo = ref('')」で宣言してv-model="newTodo"を指定します。

試しに<p>{{ newTodo }}</p>をコード内に記述すると、inputに入力した内容が{{ newTodo }}に表示されます。

※ <p>{{ newTodo }}</p>の部分は表示が確認できたらTodoリストでは使わないので削除してください。

<script setup>
import { ref } from 'vue'

const newTodo = ref('')
</script>

<template>
  <form>
    <input v-model="newTodo">
    <button>追加</button>
    <p>{{ newTodo }}</p>
  </form>
  <ul>
    <li>foo <button>X</button></li>
    <li>bar <button>X</button></li>
    <li>baz <button>X</button></li>
  </ul>
</template>

v-modelを使ったサンプル

3. Todoリストのデータをv-forで表示

ulタグ内のfoo, bar, bazの3つをv-forで表示できるようにします。

「let id = 0」を宣言してtodosの配列をref([])で作成し、以下のようにliタグにv-forを書くことで反映されます。

<script setup>
import { ref } from 'vue'

let id = 0
const newTodo = ref('')
const todos = ref([
  { id: id++, text: 'foo' },
  { id: id++, text: 'bar' },
  { id: id++, text: 'baz' },
])
</script>

<template>
  <form>
    <input v-model="newTodo">
    <button>追加</button>
    <p>{{ newTodo }}</p>
  </form>
  <li v-for="todo in todos" :key="todo.id">
    {{ todo.text }}
    <button>X</button>
  </li>
</template>

4. Todoリストに追加する関数の作成

Todoリストに追加する関数を作成します。

Todoは「const todos」の配列にデータを入れるので、ここにpush()で追加されるようにすれば反映されます。

まず、配列に追加するための関数を以下のように作成します。

function addTodo() {
  const todo = { id: id++, text: newTodo.value }
  todos.value.push(todo)
  newTodo.value = ''
}

2. で述べたとおり、inputタグにv-model="newTodo"を書いてあるので、newTodo.valueでテキストを取得できます。

あとはtodos.value.push(todo)で配列に入れて、input内のvalueを消せばTodoリストの追加処理になります。

<script setup>
import { ref } from 'vue'

let id = 0
const newTodo = ref('')
const todos = ref([
  { id: id++, text: 'foo' },
  { id: id++, text: 'bar' },
  { id: id++, text: 'baz' },
])

function addTodo() {
  const todo = { id: id++, text: newTodo.value }
  todos.value.push(todo)
  newTodo.value = ''
}
</script>

<template>
  <form @submit.prevent="addTodo">
    <input v-model="newTodo">
    <button>追加</button>
  </form>
  <li v-for="todo in todos" :key="todo.id">
    {{ todo.text }}
    <button>X</button>
  </li>
</template>

5. Todoリストを削除する関数の作成

Xボタンを押した際に削除するには配列を削除するメソッドを使用します。

JavaScriptで配列を削除するにはslice, splice, shift, pop, filterなどが使用されますが、このTodoリストはfilterで処理します。

function removeTodo(todo) {
  todos.value = todos.value.filter((t) => t !== todo)
}

Todoリストを削除する関数を作成したらXのbuttonタグに「@click="removeTodo(todo)」を追加します。

こうすることでXを押したときにtodoを引数で取得して、関数内のtodo.value.filterでtodo以外を返す処理になります。

<script setup>
import { ref } from 'vue'

let id = 0
const newTodo = ref('')
const todos = ref([
  { id: id++, text: 'foo' },
  { id: id++, text: 'bar' },
  { id: id++, text: 'baz' },
])

function addTodo() {
  const todo = { id: id++, text: newTodo.value }
  todos.value.push(todo)
  newTodo.value = ''
}

function removeTodo(todo) {
  todos.value = todos.value.filter((t) => t !== todo)
}
</script>

<template>
  <form @submit.prevent="addTodo">
    <input v-model="newTodo">
    <button>追加</button>
  </form>
  <li v-for="todo in todos" :key="todo.id">
    {{ todo.text }}
    <button @click="removeTodo(todo)">X</button>
  </li>
</template>

Vueで作成したTodoリストのサンプル

空の内容を送信しない場合

前述のサンプルだと何も入力していなくても追加ボタンを押すと追加されます。

そのため、入力内容がない場合は追加処理をしないよう、以下のようにifで条件分岐させるのが適切です。

function addTodo() {
  const newTodo = newTodo.value.trim()
  if (newTodo !== '') {
    const todo = { id: id++, text: newTodo }
    todos.value.push(todo)
    newTodo.value = ''
  }
}

同じの内容を登録しない場合

すでに同じ内容を登録したくない場合はsome()でtodosに同じテキストがすでにないかチェックして、以下のようにifで条件分岐させます。

function addTodo() {
  if (!todos.value.some((t) => t.text === newTodo.value)) {
    const todo = { id: id++, text: newTodo.value }
    todos.value.push(todo)
    newTodo.value = ''
  }
}