# 5.3 Vue の基本書き方(基礎文法編)
前回は Vite + Vue 3 を使って Hello World を体験した。
ここからはもう少し踏み込み、Vue の基本的な書き方を ToDo リスト を題材に学んでいく。
1. Vue の基本ディレクティブ
Vue では、HTML テンプレートに「ディレクティブ」と呼ばれる属性を付けて制御する。
-
v-for
… リストの繰り返し -
v-if
/v-else
… 条件分岐 -
v-model
… フォーム入力の双方向バインディング -
@click
… イベント(クリック)のバインド
これらを組み合わせると、業務システムでもよく使う 一覧・フォーム・ボタン操作 が簡単に書ける。
たとえば「受注リストを表示する」「チェックボックスで状態を切り替える」などは、これらのディレクティブを組み合わせるだけで実装可能になる。
2. ToDo リスト(素の Vue 実装)
まずは Vue の基本機能だけを使ったシンプルな ToDo リストを作る。
src/views/Todo.vue
<template>
<div>
<h2>ToDo リスト</h2>
<!-- 新規追加フォーム -->
<input v-model="newTask" placeholder="新しいタスクを入力" />
<button @click="addTask">追加</button>
<!-- タスクリスト -->
<ul>
<li v-for="(task, index) in tasks" :key="index">
<span :style="{ textDecoration: task.done ? 'line-through' : 'none' }">
{{ task.title }}
</span>
<button @click="toggleDone(index)">
{{ task.done ? "未完了に戻す" : "完了にする" }}
</button>
<button @click="removeTask(index)">削除</button>
</li>
</ul>
<!-- タスクがないとき -->
<p v-if="tasks.length === 0">タスクはありません</p>
</div>
</template>
<script setup>
import { ref } from "vue";
const newTask = ref("");
const tasks = ref([]);
const addTask = () => {
if (newTask.value.trim() === "") return;
tasks.value.push({ title: newTask.value, done: false });
newTask.value = "";
};
const toggleDone = (index) => {
tasks.value[index].done = !tasks.value[index].done;
};
const removeTask = (index) => {
tasks.value.splice(index, 1);
};
</script>
解説
-
v-model="newTask"
→ 入力フォームの値とnewTask
変数を常に同期。 -
v-for="(task, index) in tasks"
→ 配列tasks
をループしてリスト表示。 -
:style="{ textDecoration: task.done ? 'line-through' : 'none' }"
→ 完了したタスクに打消し線をつける。 -
@click="toggleDone(index)"
→ ボタンクリックで完了/未完了を切り替える。 -
v-if="tasks.length === 0"
→ タスクが一件もなければメッセージを表示。
👉 この小さな例だけで Vue の基本文法をほぼ一通り体験できる。
3. Vuetify の導入
素の Vue だけでも動作するが、業務システムでは UI の統一感 が重要。
そのため、UI コンポーネントライブラリの Vuetify を導入する。
なぜ Vuetify を使うのか
-
業務システムに必要な UI 部品が揃っている
入力フォーム、一覧テーブル、ダイアログなどを最初から利用可能。 -
Material Design 準拠で統一感がある
デザイナーがいなくても「それっぽい」見た目になる。 -
開発効率が高い
ボタンや入力欄を組み合わせるだけで実用的な画面がすぐ作れる。 -
素の CSS より保守性が高い
大規模システムでも UI がバラバラにならない。
👉 Vuetify は「必ず使わなければならない」わけではなく、効率を高めるための道具。
もし制約で使えなければ素の CSS でも問題ない。
インストール
npm install vuetify@latest
main.js
に Vuetify を追加する。
// src/main.js
import { createApp } from "vue";
import App from "./App.vue";
import router from "./router";
import { createPinia } from "pinia";
// Vuetify
import "vuetify/styles";
import { createVuetify } from "vuetify";
import * as components
from "vuetify/components";
import * as directives
from "vuetify/directives";
const vuetify = createVuetify({
components,
directives,
});
createApp(App).use(router).use(createPinia()).use(vuetify).mount("#app");
解説
-
import "vuetify/styles";
→ Vuetify のスタイルを読み込む。 -
createVuetify({ components, directives })
→ Vuetify を Vue アプリに登録。 -
.use(vuetify)
→ これで<v-btn>
や<v-text-field>
が使えるようになる。
4. ToDo リスト(Vuetify 版)
同じ機能を Vuetify のコンポーネントで書き直すと、見た目が一気に業務システムっぽくなる。
<template>
<v-container>
<h2 class="mb-4">ToDo リスト</h2>
<!-- 入力フォーム -->
<v-row>
<v-col cols="8">
<v-text-field
v-model="newTask"
label="新しいタスク"
outlined
dense
/>
</v-col>
<v-col cols="4">
<v-btn color="primary" @click="addTask">追加</v-btn>
</v-col>
</v-row>
<!-- タスク一覧 -->
<v-list two-line>
<v-list-item v-for="(task, index) in tasks" :key="index">
<v-list-item-content>
<v-list-item-title
:class="{ 'text-decoration-line-through': task.done }"
>
{{ task.title }}
</v-list-item-title>
</v-list-item-content>
<v-list-item-action>
<v-btn small @click="toggleDone(index)">
{{ task.done ? "未完了" : "完了" }}
</v-btn>
<v-btn small color="error" @click="removeTask(index)">削除</v-btn>
</v-list-item-action>
</v-list-item>
</v-list>
<!-- タスクがないとき -->
<v-alert v-if="tasks.length === 0" type="info" dense>
タスクはありません
</v-alert>
</v-container>
</template>
<script setup>
import { ref } from "vue";
const newTask = ref("");
const tasks = ref([]);
const addTask = () => {
if (newTask.value.trim() === "") return;
tasks.value.push({ title: newTask.value, done: false });
newTask.value = "";
};
const toggleDone = (index) => {
tasks.value[index].done = !tasks.value[index].done;
};
const removeTask = (index) => {
tasks.value.splice(index, 1);
};
</script>
解説
-
<v-text-field>
… Vue の<input>
に相当。見た目が整ってラベル付きになる。 -
<v-btn>
… ボタン。color="primary"
でシステム共通カラーを適用。 -
<v-list>
/<v-list-item>
… リスト表示用コンポーネント。業務システムでもよく使う。 -
<v-alert>
… 情報メッセージを目立つ形で表示。
👉 同じ処理でも Vuetify を使うと 即戦力な UI になる。
💡 AI 活用のポイント
-
画面デザイン調整は AI が苦手
Vuetify を使っていても、<v-text-field>
とその横の<v-btn>
の縦位置がずれるなど、微妙な崩れはよく起こる。 -
AI にコードや画面を見せても一発で直るとは限らない
「直して」と言っても 1 回で解決しないことが多く、最悪は直らない場合もある。 -
自力で直す方が早いケースもある
レイアウト調整に限っては CSS の微修正で済む場合が多いため、自分で調整する力を持っておくと効率的。 -
AI を繰り返し使うなら “戦略” が必要
何度か試して直らない場合は、別のやり方(コンポーネントの入れ替えや配置の変更)を提案させる。
ただし、既存アプリ全体の整合性が崩れるリスクがあるので注意。 -
大事なのは整合性の視点
見た目を直すことだけに集中せず、システム全体の一貫性を保ちながら調整する姿勢が重要。
5. まとめ
-
素の Vue で基本文法を体験(
v-for
,v-if
,v-model
,@click
) - Vuetify を導入して UI をリッチ化(フォーム・リスト・ボタン・アラート)
- 業務システムでは Vuetify のような UI ライブラリを使うのが前提
👉 次回は axios を使った API 呼び出し に進み、Django REST Framework の API と連携して「一覧画面」を作る。
Discussion