🕌

Vue.jsについて1から学ぶ

に公開

初めに

Vue.jsについて、学ぶ機会があったので、軽くまとめていきたいと思います。
(初心者のため優しい目で見てください)
この記事は以下についてまとめています。

  • アプリケーションインスタンス(createApp)
  • データバイディング
  • ディレクティブ
  • 双方向データバインディングとは?
  • computedについて
  • watchについて

Vue.jsとは?

Vue.jsは、JavaScriptで動的なWebアプリケーションを作るためのフロントエンド・フレームワークです。

アプリケーションインスタンス(createApp)

Vue 3 では createApp 関数を使って「アプリケーションインスタンス」を作成し、その中でルートコンポーネントを登録してマウントします。

データバインディング ({{ }})

データバインディングは、アプリケーションインスタンスのデータをHTMLに表示する仕組みです。テキスト補間とも呼ばれ、{{ }}(マスタッシュ構文)を使います。

ディレクティブ

ディレクティブは、v-というプレフィックスを持つ特殊なHTML属性で、DOM(Document Object Model)に特定の振る舞いをさせます。

v-bind

  • リアクティブデータを HTML 要素の属性に反映させます。短縮形は :
  • 構文
  v-bind:属性名="プロパティ名"
  • 簡単な例
<template>
  <img v-bind:src="imageUrl" alt="写真">
  <!-- 省略形 -->
  <img :src="imageUrl" alt="写真">
</template>

<script setup>
const imageUrl = 'https://example.com/pic.png'
</script>

v-if / v-else / v-show

  • v-ifは、条件がtrueの場合に要素をレンダリング(DOMに追加)し、falseの場合はDOMから完全に削除します。これにより、要素が存在しなくなります。

    • v-if
      条件がtrueの場合にのみ、要素をDOMに挿入します。

    • v-else-if
      v-ifの条件がfalseだった場合に、次の条件を評価します。

    • v-else
      上記すべての条件がfalseだった場合に表示されます。

<div v-if="type === 'A'">
  A
</div>
<div v-else-if="type === 'B'">
  B
</div>
<div v-else>
  C
</div>

v-showも要素の表示・非表示を制御しますが、常にDOMに要素が存在します。条件がfalseの場合、CSSのdisplay: none;を適用することで非表示にします。要素が頻繁に切り替わる場合に適しています。

  • v-if を使う時
    • 要素の表示切替がまれ
    • 初期描画時に非表示で良い(DOM を作らない方が軽い)
    • 非表示中は内部状態やイベントリスナーも不要にしたい場合
  • v-show を使う時
    • 要素を頻繁に表示/非表示する(例:タブ切り替え、アコーディオンメニュー)
    • 内部状態やフォーム入力値を保持したまま非表示にしたい場合

v-for

  • 役割は、JavaScriptの配列やオブジェクトのデータに基づいて、HTMLの要素を自動的に複数生成することです。これにより、手動で同じようなHTMLを何度も書く手間が省けます。key は基本的にユニークな識別子を渡す必要があります。
<template>
  <ul>
    <li v-for="fruit in fruits" :key="fruit.id">
      {{ fruit.name }}
    </li>
  </ul>
</template>

<script setup>
const fruits = [
  { id: 1, name: 'りんご' },
  { id: 2, name: 'バナナ' },
  { id: 3, name: 'ぶどう' }
]
</script>

v-on (イベントハンドリング)

  • ユーザーの操作(クリック、キー入力、ホバーなど)に対応して、テンプレートから呼び出せる関数のことです。これにより、イベントに応じた動的な振る舞いをアプリケーションに持たせることができます。
  • 簡単な例
<button v-on:click="handleClick">クリックしてください</button>
  • 省略形
    v-onは頻繁に使用されるため、省略記法としてアットマーク @ を使うことができます。
<button @click="handleClick">クリックしてください</button>

双方向データバインディングとは?

JavaScript のデータと HTML の表示(UI)が、お互いにリアクティブに同期される仕組みです。

つまり…

ユーザーが画面に入力した内容は即座にデータに反映され、
データが変更されれば、画面の表示も自動で更新される。

この両方向の同期が 双方向データバインディング です。

種類 説明
一方向バインディング データ → 画面だけの更新(例: {{ message }}
双方向バインディング データ ↔ 画面の両方が同期(例: v-model

computedについて

  • computedは算出プロパティ(computed property) と呼ばれています。
  • データや他の状態から派生した値を定義するために使います。
  • 単純に関数を呼び出してもいいのですが、computed を使うと以下のメリットがあります。
    • 必要に応じて再計算される → 依存している値が変わったときにだけ再計算され、それ以外のときは前回の結果を使う。
    • 宣言的に書ける → 「この値はこの状態から自動的に計算される」と明確にできる。

例1

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

// 基本データ
const firstName = ref('Hoge')
const lastName = ref('Hogehoge')

// 算出プロパティ
const fullName = computed(() => {
  return `${firstName.value} ${lastName.value}`
})
</script>

<template>
  <p>: <input v-model="firstName" /></p>
  <p>: <input v-model="lastName" /></p>
  <p>フルネーム: {{ fullName }}</p>
</template>

解説

  • firstName や lastName を更新すると、fullName も自動で更新されます。
  • computed は依存している値 (firstName, lastName) が変わらない限り再評価されません。
    実行結果

例2(getter/setter付き)

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

const firstName = ref('Hoge')
const lastName = ref('Hogehoge')

const fullName = computed({
  get() {
    return `${firstName.value} ${lastName.value}`
  },
  set(newValue) {
    const parts = newValue.split(' ')
    firstName.value = parts[0] || ''
    lastName.value = parts[1] || ''
  }
})
</script>

<template>
  <input v-model="fullName" />
  <p>: {{ firstName }}</p>
  <p>: {{ lastName }}</p>
</template>

解説
この場合、<input v-model="fullName" /> に入力すると firstName と lastName にも反映されます。
実行結果

getter/setterあり・なしの違いを整理してみる。

  1. getterだけのcomputed
const fullName = computed(() => {
  return `${firstName.value} ${lastName.value}`
})
  1. getter/setter両方あるcomputed
const fullName = computed({
  get() {
    return `${firstName.value} ${lastName.value}`
  },
  set(newValue) {
    const parts = newValue.split(' ')
    firstName.value = parts[0] || ''
    lastName.value = parts[1] || ''
  }
})

まとめると、、、、

  • getterのみ
    「フルネームを表示したい」だけ。入力は firstName と lastName に直接する。

  • getter + setter
    「フルネームを1つの input で編集したい」。fullName を直接更新すると裏で firstName とlastName に分解されて反映される。

watchについて

  • watchは指定したリアクティブな値を監視して、副作用を実行するための仕組みです。
  • 「値の変化に応じて何か処理したいとき」に使います。
  • 似ているcomputedは「新しい値を返す」ために使うのに対し、watch は「値が変わったときに処理を走らせる」ために使います。

例1(refを監視)

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

const count = ref(0)

watch(count, (newValue, oldValue) => {
  console.log(`count が ${oldValue} から ${newValue} に変わりました!`)
})
</script>

<template>
  <button @click="count++">カウントアップ</button>
  <p>{{ count }}</p>
</template>

実行結果

  • count が変わるたびにコールバックが呼ばれる。
  • watch のコールバック引数には 新しい値・古い値 が渡される。

例2(複数の値の変化に応じて処理を実行)

今回は、「複数の値で条件分岐して背景色を変更する」ケース。

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

const temperature = ref(20)
const humidity = ref(50)
const backgroundColor = ref('white')

watch([temperature, humidity], ([temp, hum]) => {
  if (temp > 30 && hum > 70) {
    backgroundColor.value = 'red'
  } else if (temp < 10) {
    backgroundColor.value = 'blue'
  } else {
    backgroundColor.value = 'green'
  }
})
</script>

<template>
  <div :style="{ backgroundColor: backgroundColor, padding: '20px' }">
    <p>Temperature: <input type="number" v-model="temperature" /></p>
    <p>Humidity: <input type="number" v-model="humidity" />%</p>
  </div>
</template>

解説

  • watch に配列を渡すことで、複数の 値を同時に監視できます。
  • v-model でバインドされた入力が変わるたびに watch が呼ばれるので、背景色が即座に更新されます。

実行結果

Discussion