初心者向け!Vue 3 を使った簡単なアプリ開発入門

その他

はじめに

これまでの記事でVue.jsの環境構築、基本構文、非同期処理の方法までを解説しました。

環境構築

Vue.js入門:特徴から環境構築まで完全ガイド
Vue.jsの基本から環境構築まで初心者向けにわかりやすく解説!CDN版とVue CLIの違い、セットアップ方法、便利なツールも紹介します。

基本構文

Vue.jsの基本構文からコンポーネントの使い方まで解説
Vue.jsの基本構文からコンポーネントの使い方まで初心者向けに詳しく解説。簡単なサンプルコード付きで、実践しながら学べます。

非同期処理

Vue 3でAPI連携!fetchとAxiosの使い方
Vue 3でAPIからデータを取得する方法を初心者向けに解説!fetchとAxiosの違い、非同期処理、エラーハンドリングの実装方法を紹介。

構文だけでは開発イメージが持てないと思うので、Vue 3 を使って簡単なアプリを作成する方法を解説します!

TODOリストアプリの作成(ローカルストレージ利用)

Vue 3 の ref() を使ってタスクを管理し、localStorage を活用してデータを保持する TODOリストアプリ を作成します。
ページをリロードしてもタスクが消えないように localStorage を利用し、基本的な CRUD(追加・削除・保持)機能を実装します。

プロジェクトディレクトリ

todo-app/
│── public/ 
│── src/
│   ├── assets/ 
│   ├── components/
│   │   ├── TodoList.vue  ← TODOリストのコンポーネント
│   ├── App.vue  ← メインレイアウト
│   ├── main.js  ← Vue インスタンスの作成
│   ├── store.js  ← (オプション) 状態管理を使う場合
│── package.json
│── vite.config.js  (または vue.config.js)
│── index.html

TODOリストの詳細な実装

実装する機能

  • タスクの追加
  • タスクの削除
  • ローカルストレージに保存し、リロードしてもデータを保持

App.vue(メインレイアウト)

<script setup>
import TodoList from './components/TodoList.vue';
</script>

<template>
  <div>
    <h1>Vue 3 TODOリスト</h1>
    <TodoList />
  </div>
</template>
  • TodoList.vueコンポーネントとして読み込む ことで、構成を整理しています。

TodoList.vue(TODOリストのコンポーネント)

<script setup>
import { ref, onMounted } from 'vue';

const tasks = ref([]);  // タスクの配列
const newTask = ref(''); // ユーザーが入力するタスク

// ページロード時にローカルストレージからデータを取得
onMounted(() => {
  const savedTasks = localStorage.getItem('tasks');
  if (savedTasks) {
    tasks.value = JSON.parse(savedTasks);
  }
});

// タスクを追加
const addTask = () => {
  if (newTask.value.trim() === '') return; // 空白チェック
  tasks.value.push(newTask.value); // タスク追加
  localStorage.setItem('tasks', JSON.stringify(tasks.value)); // localStorage に保存
  newTask.value = ''; // 入力フィールドをクリア
};

// タスクを削除
const removeTask = (index) => {
  tasks.value.splice(index, 1); // 指定したタスクを削除
  localStorage.setItem('tasks', JSON.stringify(tasks.value)); // localStorage を更新
};
</script>

<template>
  <div class="todo-container">
    <h2>TODOリスト</h2>
    <div class="todo-input">
      <input v-model="newTask" placeholder="新しいタスクを入力" />
      <button @click="addTask">追加</button>
    </div>
    <ul>
      <li v-for="(task, index) in tasks" :key="index">
        {{ task }}
        <button @click="removeTask(index)">削除</button>
      </li>
    </ul>
  </div>
</template>

<style scoped>
.todo-container {
  max-width: 400px;
  margin: 0 auto;
  padding: 20px;
  background: #f8f9fa;
  border-radius: 8px;
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}
.todo-input {
  display: flex;
  gap: 10px;
}
input {
  flex: 1;
  padding: 8px;
  border: 1px solid #ccc;
  border-radius: 4px;
}
button {
  padding: 8px 12px;
  background: #28a745;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}
button:hover {
  background: #218838;
}
ul {
  list-style: none;
  padding: 0;
}
li {
  display: flex;
  justify-content: space-between;
  padding: 8px;
  background: white;
  margin: 5px 0;
  border-radius: 4px;
}
li button {
  background: #dc3545;
}
li button:hover {
  background: #c82333;
}
</style>

onMounted() で localStorage からデータを取得

onMounted(() => {
  const savedTasks = localStorage.getItem('tasks');
  if (savedTasks) {
    tasks.value = JSON.parse(savedTasks);
  }
});
  • localStorage.getItem('tasks') で保存されたタスクを取得
  • JSON.parse() を使ってオブジェクトに変換し、tasks.value に格納

タスクを追加する処理

const addTask = () => {
  if (newTask.value.trim() === '') return; // 空白チェック
  tasks.value.push(newTask.value); // タスク追加
  localStorage.setItem('tasks', JSON.stringify(tasks.value)); // localStorage に保存
  newTask.value = ''; // 入力フィールドをクリア
};
  • newTask.value をリストに追加
  • localStorage にデータを保存
  • 入力欄をクリア

タスクを削除する処理

const removeTask = (index) => {
  tasks.value.splice(index, 1); // 指定したタスクを削除
  localStorage.setItem('tasks', JSON.stringify(tasks.value)); // localStorage を更新
};
  • splice() を使って tasks.valueindex 番目の要素を削除
  • 削除後に localStorage を更新

API を使った天気予報アプリの作成

外部 API(OpenWeather API)を利用して、ユーザーが入力した都市の天気情報を取得・表示するアプリを作成します。

プロジェクトディレクトリ

weather-app/
│── src/
│   ├── components/
│   │   ├── Weather.vue  ← 天気情報のコンポーネント
│   ├── App.vue  ← メインレイアウト
│   ├── main.js  ← Vue インスタンスの作成
│── package.json
│── vite.config.js  (または vue.config.js)
│── index.html

APIキーの取得

天気の情報を取得できるようにするためにOpen Weather MapからAPIキーを取得します。

Current weather and forecast - OpenWeatherMap
OpenWeather provides comprehensive weather data services, including current, forecast, and historicalweather information...
  • ヘッダーのサインインをクリックします。
Screenshot
  • Create an Accountをクリックします。
  • 必要情報を入力し、アカウントを作成します。
  • メールを開きメール認証を完了させます。
  • ホーム画面から、ヘッダーの「アカウント」→「My API Keys」を選択します。
Screenshot
  • APIキーをコピーします。

天気予報アプリの詳細な実装

完成する機能

  • ユーザーが入力した都市の天気情報を取得
  • ref() を使ってリアクティブなデータを管理
  • 取得したデータを Vue のテンプレートに表示

App.vue(メインレイアウト)

<script setup>
import Weather from './components/Weather.vue';
</script>

<template>
  <div>
    <h1>天気予報アプリ</h1>
    <Weather />
  </div>
</template>

Weather.vue(天気情報のコンポーネント)

  • YOUR_API_KEYに先ほど取得したAPI KEYを入力します。
    これは秘匿情報なので、Gitなど公開しないでください。
<script setup>
import { ref } from 'vue';
import axios from 'axios';

const city = ref('');
const weather = ref(null);
const errorMessage = ref('');
const apiKey = 'YOUR_API_KEY';

// 天気データ取得用関数
const fetchWeather = async () => {
  if (!city.value.trim()) {
    errorMessage.value = '都市名を入力してください';
    return;
  }

  try {
    const response = await axios.get(
  `https://api.openweathermap.org/data/2.5/weather?q=${encodeURIComponent(city.value)}&appid=${apiKey}&units=metric&lang=ja`
  );
    weather.value = response.data;
    errorMessage.value = '';
  } catch (error) {
    errorMessage.value = '天気情報の取得に失敗しました。都市名を確認してください。';
  }
};
</script>

<template>
  <div class="weather-container">
    <h2>天気予報</h2>
    <div class="input-container">
      <input v-model="city" placeholder="都市名を入力" />
      <button @click="fetchWeather">検索</button>
    </div>
    <p v-if="errorMessage" class="error">{{ errorMessage }}</p>
    <div v-if="weather" class="weather-info">
      <h3>{{ weather.name }} の天気</h3>
      <p>気温: {{ weather.main.temp }}℃</p>
      <p>天気: {{ weather.weather[0].description }}</p>
    </div>
  </div>
</template>

<style scoped>
.weather-container {
  max-width: 400px;
  margin: 0 auto;
  padding: 20px;
  background: #f8f9fa;
  border-radius: 8px;
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}
.input-container {
  display: flex;
  gap: 10px;
}
input {
  flex: 1;
  padding: 8px;
  border: 1px solid #ccc;
  border-radius: 4px;
}
button {
  padding: 8px 12px;
  background: #007bff;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}
button:hover {
  background: #0056b3;
}
.error {
  color: red;
  margin-top: 10px;
}
.weather-info {
  margin-top: 20px;
  padding: 10px;
  background: #fff;
  border-radius: 4px;
}
</style>

コードの解説

  1. 都市名を入力し、検索ボタンを押すと天気情報を取得
  2. API 取得が成功すれば weather にデータを格納し、画面に表示
  3. エラー発生時は errorMessage にエラーメッセージを表示
  4. v-model を使い、リアルタイムに入力を反映
  5. axios.get() を使って OpenWeather API からデータ取得
  6. 都市名が空の場合や API 取得に失敗した場合にエラーメッセージを表示

フォームバリデーションの実装

ユーザーが入力した 名前・メール・パスワード をバリデーションし、正しいデータのみ送信できるようにします。

完成する機能

  • v-model を使ってリアルタイムにフォーム入力を反映
  • 必須チェック・メール形式チェック・パスワードの長さチェックを実装

App.vue(フォームバリデーションの実装)

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

const name = ref('');
const email = ref('');
const password = ref('');
const errors = ref([]);

const validateForm = () => {
  errors.value = [];

  if (!name.value.trim()) {
    errors.value.push('名前を入力してください');
  }

  if (!email.value.trim()) {
    errors.value.push('メールアドレスを入力してください');
  } else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email.value)) {
    errors.value.push('正しいメールアドレスを入力してください');
  }

  if (!password.value.trim()) {
    errors.value.push('パスワードを入力してください');
  } else if (password.value.length < 6) {
    errors.value.push('パスワードは6文字以上で入力してください');
  }
};
</script>

<template>
  <div class="form-container">
    <h2>ユーザー登録</h2>
    <div class="input-group">
      <input v-model="name" placeholder="名前" />
      <input v-model="email" placeholder="メールアドレス" />
      <input type="password" v-model="password" placeholder="パスワード" />
    </div>
    <button @click="validateForm">登録</button>
    <ul v-if="errors.length" class="error-list">
      <li v-for="error in errors" :key="error">{{ error }}</li>
    </ul>
  </div>
</template>

<style scoped>
.form-container {
  max-width: 400px;
  margin: 0 auto;
  padding: 20px;
  background: #f8f9fa;
  border-radius: 8px;
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}
.input-group {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
input {
  padding: 8px;
  border: 1px solid #ccc;
  border-radius: 4px;
}
button {
  padding: 8px 12px;
  background: #28a745;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}
button:hover {
  background: #218838;
}
.error-list {
  color: red;
  margin-top: 10px;
}
</style>

コードの解説

  1. errors.value にエラーリストを格納し、バリデーション結果を表示
  2. メールアドレスの形式チェックは正規表現 (/^[^\s@]+@[^\s@]+\.[^\s@]+$/) を使用
  3. password.value.length < 6 でパスワードの長さをチェック
  4. エラーがある場合、リストとして画面に表示
  5. バリデーションが通らないと登録ボタンを押しても処理が進まない

Vue.js アプリ開発の次のステップ

ここまでで Vue の基本を学びましたが、さらにレベルアップするために 次のステップ に進みましょう!

Vue Router を使ってアプリを複数ページ化する

Vue 3 の Vue Router を初心者向けに解説!【SPA開発の基礎】
Vue 3の公式ルーティングライブラリ「Vue Router」の基本を解説!SPAの仕組み、ページ遷移の実装、動的ルートの活用方法を詳しく紹介します。

Pinia を使ってデータを一元管理する

Vue 3 の状態管理ライブラリ「Pinia」を初心者向けに解説!
Vue 3の状態管理ライブラリ「Pinia」の基本を初心者向けに解説!インストール方法からstate・actions・gettersの使い方、実践例まで詳しく紹介します。

まとめ

  • Vue 3 を使ったアプリ開発の流れを学んだ
  • TODOリスト、天気予報アプリ、フォームバリデーションを実装した
  • 次のステップとして Vue Router や Pinia に挑戦

Vue での開発を楽しみながら、どんどんアプリを作っていきましょう!

コメント

タイトルとURLをコピーしました