概要
Nuxt3がすごいらしいので、引き続きToDoアプリを作りながら学んでいきたいと思います。
イベントハンドリング・リストレンダリングを使って、動作の確認をしていきます。
内容はVue.js初心者向けです。
前回の記事
今回の記事のゴール
リストレンダリング、イベントハンドリングを使って入力内容を画面に表示できる。
完成コード
<template>
<div>
<h1>ToDoApp</h1>
<h2>タスク追加</h2>
<input v-model="taskName"><button @click="addTask()">追加</button>
<h2>タスク名</h2>
<div v-for="taskName in taskNameList" :key="taskName">
{{ taskName }}<button @click="completeTask(taskName)">完了</button>
</div>
</div>
</template>
<script setup lang="ts">
const taskNameList = ref<string[]>(['Vue', 'Vue3', 'Nuxt3']);
const taskName = ref<string>('');
const addTask = () => {
if (taskName.value === '') {
return;
}
taskNameList.value.push(taskName.value);
taskName.value = '';
}
const completeTask = (completedTaskName: string) => {
taskNameList.value = taskNameList.value.filter((taskName) => completedTaskName !== taskName);
}
</script>
書いていく
ディレクティブについて
template内でv-
という接頭辞を持ち、HTML要素の属性として定義できるものをディレクティブと呼びます。
Vueによって提供される特別な属性で、template内の要素にリアクティブな振る舞いを割り当てることができます。
前回のv-modelもディレクティブの一つで、input要素のvalue属性に対してリアクティブな振る舞いを提供しました。
他にもv-for
ディレクティブやv-if
ディレクティブなどが用意されています。
リストレンダリング
v-for
ディレクティブを用いることで、for文と同じように配列のデータを一件ずつ表示することができます。
v-for="配列の中の一要素 in 配列"
といった形で表します。
まずはscriptの中から確認します。
表示確認を行うため、仮データを作成していきます。
変数名はtaskNameList
とし、リアクティブなデータを示すためref
を使用します。ref
の隣にある<>
は型名を表しているため、string型の配列を意味する<string[]>
を記述しておきます。
<script setup lang="ts">
const taskNameList = ref<string[]>(['vue', 'Vue3', 'Nuxt3']);
</script>
仮データが準備できたので、次はtemplateです。
先ほど紹介したv-for
ディレクティブを使用します。
v-for="taskName in taskNameList"
とすることで配列内の'apple', 'banana', 'cherry'をそれぞれ出力することができます。
<template>
<div>
<h2>タスク名</h2>
<div v-for="taskName in taskNameList" :key="taskName">
{{ taskName }}
</div>
</div>
</template>
補足(keyについて)
div要素の中にkey
という属性が存在しているのがわかるかと思います。
これは、並び替えやデータの削除、追加などを行う際に、Vueがどの要素かを一意に特定するための重要な要素になります。key
には文字列もしくは数値を指定します。
補足(keyの前にある「:」について)
「:」はv-bind
ディレクティブを表しています。頻繁に使用されるため、省略形が使用できるようになっています。
v-bind
はその名の通り、属性とプロパティとを結びつける役割があります。
(今回はid属性に対して、taskNameプロパティを結びつけている)
イベントハンドリング
v-onディレクティブを用いて、イベント発火時(クリックなど)にJavaScriptを実行することができます。
v-bind同様にこちらも省略表記が可能で、@
で表記できます。
例えば@click="addTask()"
だと、クリック時にaddTask
関数を実行するということになります。
タスクの追加処理
タスクの追加処理を実装して、タスクのクリックイベントを実装していきます。
templateから見ていきます。
先ほどのv-for
の上に、v-model
ディレクティブを使用したinput要素と、追加ボタンを設置します。
追加ボタンはクリック時に、addTask
関数を呼び出せるよう@click="addTask()"
とします。
<template>
<div>
<input v-model="taskName">
<button @click="addTask()">追加</button>
<h2>タスク名</h2>
<div v-for="taskName in taskNameList" :key="taskName">
{{ taskName }}
</div>
</div>
</template>
次にscriptです。
addTask
関数を新たに定義します。
taskName
はv-model
によって、input要素と繋がっているので、入力されているを常に保持しています。
そのため、クリック時にtaskName
の値は、input要素に入力されている値になります。
あとは、taskNameList
配列にpush
をすることで加えることで、画面に入力した要素が追加されます。
あとは、「空入力時に配列にデータを入れない」「追加したら初期化する」処理をして、完了です。
<script setup lang="ts">
const taskNameList = ref<string[]>(['Vue', 'Vue3', 'Nuxt3']);
const taskName = ref<string>('');
const addTask = () => {
if (taskName.value === '') {
return;
}
taskNameList.value.push(taskName.value);
taskName.value = '';
}
</script>
タスクの削除処理
最後にタスクの削除処理を追加していきます。
同じくイベントハンドリングを使います。
templateからです。
追加ボタン同様、完了ボタンを追加します。
ただし、各タスクについて完了ボタンを使用したいので、v-for
の中に用意します。
関数名はcompleteTask
としています。
また、どのタスクが完了したのかを把握させるため、引数にtaskName
を入れておきます。
<template>
<div>
<input v-model="taskName">
<button @click="addTask()">追加</button>
<h2>タスク名</h2>
<div v-for="taskName in taskNames" :key="taskName">
{{ taskName }}
<button @click="completeTask(taskName)">完了</button>
</div>
</div>
</template>
次にscriptです。
タスクの削除イコール配列からそのタスクを除けば良いので、以下の関数を用意します。
配列ようのfilterメソッドを使用して、完了したタスク名と同様のタスクを配列から削除する処理となっています。
const completeTask = (completedTaskName: string) => {
taskNames.value = taskNames.value.filter((taskName: string) => {
return completedTaskName !== taskName
});
}
あとは、タイトルをつければ完成です。
<template>
<div>
<h1>ToDoApp</h1>
<h2>タスク追加</h2>
<input v-model="taskName">
・・・省略
まとめ
画面上で動作する程度のものが完成しました。
次回はコンポーネントの分割を行っていきたいと思います。