【Vue.js】ライフサイクル（created / mounted）の違いと computed / watch の使い方



### はじめに

以下では、Vue.js のライフサイクル（created / mounted）の違いを中心に、computed と watch についてもあわせて解説します。「いつ DOM にアクセスできるか」や「どのフックでどんな処理を行うべきか」に加えて、Vue 特有の 算出プロパティ（computed） と ウォッチャ（watch） の用途も押さえておきましょう。

### 1. DOMが作成される前

#### 1-1. 主なフック
- beforeCreate
- created

Vue コンポーネントのインスタンスがまだ DOM にマウントされていない（描画されていない）段階を指します。

##### できること
1. data や computed などの状態にアクセス
   - created フック以降であれば this.dataName の読み書きが可能。
2. 初期データの設定や API 通信などのロジック実行
   - 例: created フックでバックエンドからデータを取得して data にセット。

##### できないこと
1. this.$el へのアクセス
   - DOM要素自体がまだ生成されていないため、DOM操作はできません。
2. 外部ライブラリで DOM を操作する処理
   - 例: チャートライブラリや地図ライブラリの初期化はまだできません。

##### 使用例

**コンポーネント生成時にバックエンドからデータを取得したい**

```javascript
created() {
  fetch('/api/hello')
    .then(response => response.json())
    .then(data => {
      this.message = data;
    });
}
```

**インスタンス生成時に初期値を計算してセット**

```javascript
created() {
  this.count = Math.floor(Math.random() * 10);
}
```

### 2. DOMが作成された後

#### 2-1. 主なフック
- beforeMount
- mounted
- （更新時には updated などもある）

特に mounted は DOM が描画され、this.$el が使えるようになるタイミングです。

##### できること
1. this.$el を使った DOM 操作
   - this.$el.querySelector(...) などで直接 DOM 要素を取得可能。
2. 外部ライブラリの初期化
   - 例: Chart.js, Leaflet, Google Maps など DOM が必要なもの。
3. タイマーやイベントリスナーの登録
   - DOM を前提とした処理を安全に行える。

##### できない（または非推奨）こと
- 大量のデータ更新をここで急に行うと描画遅延を引き起こす可能性がある。
- DOM操作が多すぎるとパフォーマンス低下。

##### 使用例

**特定の要素に対して外部ライブラリで描画を行う**

```javascript
mounted() {
  const chartCtx = this.$el.querySelector('#myChart');
  // Chart.jsなどを初期化
  new Chart(chartCtx, { /* ... */ });
}
```

**refs を用いた DOM アクセス**

```html
<template>
  <div>
    <div ref="myDiv">Example</div>
  </div>
</template>

<script>
export default {
  mounted() {
    console.log(this.$refs.myDiv); // <div>Example</div>
  }
};
</script>
```

### 3. computed（算出プロパティ）

#### 3-1. 役割
- data や 他の computed を元に、新しい値を“算出”して返すプロパティ
- 「テンプレート上で何度も行うと面倒な計算」をまとめて記述できる
- **キャッシュされる** ため、依存する値が変わらない限り再計算されない

##### できること
1. テンプレートに書きやすい“派生データ”を定義
2. 依存している data が変わったタイミングだけ再計算
3. 再計算結果が変わらない限り何度呼び出しても再計算しないのでパフォーマンスに優しい

##### できないこと / 注意点
- 基本的に「読み取り専用（getter）」として使う
- 値を直接変更したい場合は computed ではなく methods や watch を使うほうが安全

##### 使用例

```javascript
export default {
  data() {
    return {
      firstName: "Taro",
      lastName: "Yamada"
    };
  },
  computed: {
    fullName() {
      return this.firstName + " " + this.lastName;
    }
  }
};
```

- fullName は firstName や lastName が変わったときだけ再計算される

### 4. watch（ウォッチャ）

#### 4-1. 役割
- 特定の data や computed が **変化した瞬間** に処理を実行する仕組み
- リアクティブに値の変化を監視して、副作用的な処理を行う ときに使う

##### できること
1. API 呼び出しやログ出力など、データの変化をトリガーに実行
2. `deep: true` を指定すればオブジェクト配列の入れ子まで監視可能
3. `immediate: true` を指定すれば初回マウント時にも処理を実行

##### できないこと / 注意点
- watch は **キャッシュされない**
- 依存する値が変わったら毎回再実行される（計算に使うなら computed のほうが効率的）

##### 使用例

```javascript
export default {
  data() {
    return {
      count: 0
    };
  },
  watch: {
    count(newVal, oldVal) {
      console.log(`countが ${oldVal} から ${newVal} に変化しました`);
      // 例えば newVal に応じてAPIを呼ぶ など
    }
  }
};
```

**deep ウォッチの例**

```javascript
export default {
  data() {
    return {
      user: {
        name: "Taro",
        address: { city: "Tokyo" }
      }
    };
  },
  watch: {
    user: {
      handler(newVal) {
        console.log("user オブジェクトが変わりました: ", newVal);
      },
      deep: true
    }
  }
};
```

### 5. まとめ

#### 5-1. ライフサイクル（DOM 前後）

| タイミング | 主なフック | DOM 操作 | 主な用途 |
| --- | --- | --- | --- |
| DOM作成前 | created | 不可 | データの初期化、API通信など |
| DOM作成後 | mounted | 可能 | DOM操作・外部ライブラリの初期化 |

- DOM 作成前 (created):
  - Vue インスタンスのセットアップ、初期データ取得
  - DOM 操作はまだできない
- DOM 作成後 (mounted):
  - 画面が描画されているため this.$el にアクセス可能
  - チャートや地図などのライブラリ初期化

#### 5-2. computed vs watch

| 機能 | computed | watch |
| --- | --- | --- |
| 目的 | 派生データの算出(キャッシュあり) | データ変化をトリガーにした処理実行(副作用) |
| 返すもの | プロパティとしての値 | 関数としての副作用 (API呼び出し、ログなど) |
| 再実行タイミング | 依存する data が変わったとき | 監視対象が変わったとき（毎回実行） |
| メイン用途 | テンプレートで使う計算済みの値 | データ更新時のAPI通信や処理フロー |

- computed は「表示用の計算」に向いており、結果をキャッシュする
- watch は「値の変化をフックにして何か実行したい」ケース（非同期処理、ログ記録など）に適している

### 6. まとめの結論
- created と mounted の違い:
  - created: DOM が無い状態。データ初期化や API 通信をここで行う
  - mounted: DOM が生成済み。DOM 操作や外部ライブラリ初期化をここで行う
- computed: data から派生する「算出プロパティ」。キャッシュされるため、パフォーマンスが良い
- watch: 監視対象の値が変わった瞬間に処理を実行する。データの変化をトリガーに副作用（API 呼び出し等）を行う場合に使う

これらを使い分けることで、Vue.js コンポーネントをより適切に設計・制御できるようになります。