0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【第ニ話 ヘッダー部分のロジック】Claudeで生成したアプリの動きだけ見て Vueで実装してみた

0
Last updated at Posted at 2026-07-17

前回はアプリについて必要な機能などを抜き出したりしつつ
実装の準備をしました。

前回の記事はコチラ

今回は実際に立ち上げからヘッダーの作成までしていきます。
スクリーンショット 2026-07-17 13.55.30.png

ここのヘッダーを実際に作っていきます。

環境構築

1:compose.yamlを作成

Vue.js
services:
  node:
    image: node:22-alpine        // Node.js入りの環境(ホストにNodeを入れない)
    working_dir: /app
    volumes:
      - .:/app                   // このフォルダをコンテナの/appに接続
      - node_modules:/app/node_modules  // 依存パッケージは分離(速度と安定のため)
    ports:
      - "5173:5173"              // ブラウザ(ホスト)5173 → コンテナ5173
    command: sh -c "npm install && npm run dev"
volumes:
  node_modules:

server: {
    host: '0.0.0.0',          // コンテナの外から届くようにする
    hmr: { host: 'localhost' },  // 自動更新の通知先

2:Vueプロジェクトの雛形を作成

docker compose run --rm node npm create vue@latest .

そうするとコンソールが動き始めるのでこのように設定

Need to install the following packages:
create-vue@3.22.4
Ok to proceed? (y)  # yと入れる


> npx
> create-vue .

# 以下のように選択 
┌  Vue.js - The Progressive JavaScript Framework
│
◇  Current directory is not empty. Remove existing files and continue
│  Yes
│
◇  Package name:
│  madori
│
◇  Use TypeScript?
│  No
│
◇  Select features to include in your project: (↑/↓ to navigate, space to select, a to toggle all, enter to confirm)
│  Vitest (unit testing), Linter (error prevention), Prettier (code formatting)
│
◇  Select experimental features to include in your project: (↑/↓ to navigate, space to select, a to toggle all, enter
│   to confirm)
│  none
│
◇  Skip all example code and start with a blank Vue project?
│  Yes

Scaffolding project in /app...
│
└  Done. Now run:

   npm install
   npm run format
   npm run dev

lsにて中身できているか確認

compose.yaml		index.html		package.json	README.md		vite.config.js
eslint.config.js	jsconfig.json		public			src			vitest.config.js

ヘッダーの本体部分を実装

srcファイルの中には以下のファイルらがあり、 

__tests__
App.vue   # ここにどんどんVueの本体かいていく 
main.js     # 起動係

src/main.js(起動係。この3行が「App.vueをid=appに差し込んでね」の意味)

Vue.js
// Vue.js本体からcreateApp()関数をインポート 
import { createApp } from 'vue'
// これまでコーディングをしてきたApp.vueファイルをAppとしてインポート
import App from './App.vue'
// 下記に詳細記載
createApp(App).mount('#app')

createApp()はVueアプリケーションを作成する処理でここには
起点となる単一コンポーネントファイル(src)で渡す

mount()はcreateApp()で作ったVueアプリケーションを表示するメソッド
index.htmlのどのタグに表示するのかを引数で指定
この場合は#appとあり、idがappのdivタグ内に
レンダリングされて表示されるという仕組み

src/App.vue

Vue.js
<script setup>
import { ref } from 'vue'

const roomSizes = [
  { id: 1, name: '江戸間6畳(261×352)', width: 261, depth: 352 },
  { id: 2, name: '団地間6畳(255×340)', width: 255, depth: 340 },
  { id: 3, name: '中京間6畳(273×364)', width: 273, depth: 364 },
  { id: 4, name: '京間6畳(287×382)'  , width: 287, depth: 382 },
]

const roomWidth = ref('261') // 横幅の初期値を設定 refで追跡可能に
const roomDepth = ref('352') // 奥行の初期値を設定 refで追跡可能に

function selected(event) {
  const selectedId = Number(event.target.value)   // 文字列で届くので数値に変換
  // 配列の中身を1個ずつ取り出して仮に r と呼ぶ
  const found = roomSizes.find(r => r.id === selectedId)
  if (!found) return
  roomWidth.value = found.width
  roomDepth.value = found.depth
}

const selectedRoomId = ref(1)   // 今選ばれている規格のid。初期値は江戸間

function reset(){
  roomWidth.value = '261'
  roomDepth.value = '352'
  selectedRoomId.value = 1
}

</script>

<template>
  <div class="header">
   <h1>6畳1Kレイアウトシュミレーター MADORI</h1>
    <div class="room_layout">
      <p>畳の規格</p>
      <div class="room_select">
        <select v-model="selectedRoomId" @change="selected">
          <option v-for="r in roomSizes" :key="r.id" :value="r.id">
            {{ r.name }}
          </option>
        </select>
      </div>
      <p></p> <input type="text" v-model="roomWidth">
      <p>奥行</p> <input type="text" v-model="roomDepth">
      <button @click="reset">リセット</button>
    </div>
    <p>単位:cm /ドラッグで移動タップで選択</p> 
  </div>
</template>

<style>
body { font-family: sans-serif; }
.room_layout {
 display:flex;    /* 中に入っている要素(子要素)を横並びにする */
 align-items: center; /* 縦方向の中央揃え */
 gap: 12px; /* 要素同士の隙間を設定*/
}
</style>

App.vueの中身を深掘り

畳の規格 部分のロジック

Vue.js
//script部分
// 選択した時の初期値を決めて 置いておく箱
const roomSizes = [
  { id: 1, name: '江戸間6畳(261×352)', width: 261, depth: 352 },
  { id: 2, name: '団地間6畳(255×340)', width: 255, depth: 340 },
  { id: 3, name: '中京間6畳(273×364)', width: 273, depth: 364 },
  { id: 4, name: '京間6畳(287×382)'  , width: 287, depth: 382 },
]

const roomWidth = ref('261') // 横幅の初期値を設定 refで追跡可能に
const roomDepth = ref('352') // 奥行の初期値を設定 refで追跡可能に
const selectedRoomId = ref(1) // 今選ばれている規格のid。初期値は江戸間

// selectedRoomIdが変わるたびに自動で実行される
watch(selectedRoomId, (id) => {
  // 配列の中身を1個ずつ取り出して仮に r と呼ぶ
  const found = roomSizes.find(r => r.id === id)
  if (!found) return
  roomWidth.value = found.width
  roomDepth.value = found.depth
})

畳の規格部分の template部分

Vue.js
<div class="room_select">
  <select v-model="selectedRoomId">
   <option v-for="r in roomSizes" :key="r.id" :value="r.id">
     {{ r.name }}
   </option>
  </select>
</div>

watch(監視したいref, (新しい値) => { 反応する処理 }) という形で
「selectedRoomIdを見張っておいて、値が変わるたびに
その新しい値をidという名前で受け取って、中の処理を実行してね」という意味。
プルダウンで「団地間」を選ぶと selectedRoomId.value が 2 に変わり、
その瞬間この関数が自動で呼ばれ、id には 2 が入ってくる

リセットボタンのロジック

リセットボタンを押した時に
「畳の規格」「幅」「奥行」を初期値に戻すためのボタンを実装

Vue.js
// script部分

function reset(){
  roomWidth.value = '261'
  roomDepth.value = '352'
  selectedRoomId.value = 1
}

resetという関数を定義。
その中に初期値である 
roomWidth(横幅)→261
roomDepth(奥行き)→352
selectedRoomId(間取り番号)
id: 1, name: '江戸間6畳(261×352)', width: 261, depth: 352
これらの数値をこれに入れるよという処理

Vue.js
template部分

()


<p>畳の規格</p>
 <div class="room_select">
⭐️  <select v-model="selectedRoomId">
     <option v-for="r in roomSizes" :key="r.id" :value="r.id">
         {{ r.name }}
     </option>
        </select>
 </div>
🔴   <p></p> <input type="text" v-model="roomWidth">
🔵   <p>奥行</p> <input type="text" v-model="roomDepth">
🟢   <button @click="reset">リセット</button>


⭐️のところは「selectedRoomId」「畳の規格」
🔴が「roomWidth」「幅」
🔵が「roomDepth」「奥行」
🟢がリセットボタン

1:🟢のリセットボタンを押す
🟢の @click つまりクリックを監視し、それが実行された際script内の「reset」
が発動

2:⭐️🔴🔵の中に 関数「reset」の中の値が入る

※補足
① roomWidth.value = '261' のような「代入」が行われる(ここまでがJavaScript)

② v-modelで繋がっているやが、その変化を検知して
画面の表示を自動で書き換える(ここがVueの仕事)

JS→画面の一方向(reset関数が値を書き換え→画面に反映)だが、
Vueのv-modelにはその逆方向(画面→JS)もできる

プルダウンでユーザーが「団地間」を選んだときも同じv-model="selectedRoomId"の
繋がりを使って、今度は画面の操作がJS側のselectedRoomId.valueを書き換えるという
逆の流れが起きている

実際に作った画面

Image from Gyazo

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?