［Vue3］リアクティブシステムざっくりまとめ

# 概要
リアクティブシステムとは変数の値の変化に連動して表示内容が自動で変化すること。

# ref
変数の宣言時に`ref()`関数の第一引数に初期値を入れる。
`変数名.value = 代入値`で更新する。

```記法
const 変数名 = ref(値);
変数名.value = 新しい値;
```

```App.vue
<script setup lang="ts">
import {ref} from "vue";

const name1: Ref<string> = ref("hoge");
const name2 = ref("huga");  // stringで宣言しているため型宣言がなくても問題なし

name2.value = "Qiita";
</script>

<template>
	<p>おはよう!{{name1}}さん!</p>
	<p>こんにちは!{{name2}}さん!</p>
</template>
```

```:出力結果
おはよう！hogeさん!
こんにちは！Qiitaさん!
```
# reactive

reactive()によってリアクティブデータ化されたテンプレート変数は「オブジェクト名.プロパティ名」の 形で記述する必要がある。


```記法
const 変数名 = reactive({
    プロパティ:値,
    プロパティ:値,
    ...
});
変数名.value = 新しい値;
```

```App.vue
<script setup lang="ts">
import {reactive} from "vue";

const name = reactive({
	hoge: "hoge",
	huga: "huga",
});

name.fuga = "Qiita";
</script>

<template>
	<p>おはよう!{{name.hoge}}さん!</p>
	<p>こんにちは!{{name.fuga}}さん!</p>
</template>
```

```:出力結果
おはよう！hogeさん!
こんにちは！Qiitaさん!
```

# computed
スクリプトブロックで用意した変数や、外部から与えられた変数を使って計算した結果をリアクティブデータにする記法で算出プロパティという。
Vueのコーディング規約ではマスタッシュ構文内で式を記述することを避けるように記載があるため算出プロパティで処理を行う。
`また、算出プロパティは読み取り専用のためcomputed()で用意された変数のvalueプロパティに値を代入するとエラーとなる。
v-on:click="onClick"については[データバインドで](https://qiita.com/gone0021/items/fc780184ddcea373bfe3)後述する。

```:記法
const 変数名 = computed(
    (): データ型 => {
        計算処理;
        return 計算 結果;
     }
);
```

```App.vue
<script setup lang="ts">
import {ref, computed} from "vue";

const width: Ref<number> = ref(1);
const heigth: Ref<number> = ref(2);

function onClick() {
	width.value = 2;
}

const calc = computed(
	(): number => {
		return width.value * width.value
	}
);
</script>

<template>
	<div>
		<button v-on:click="onClick">ボタン</button>
	</div>
<div>幅 {{ width }} cmと高さ {{ heigth}} cmの長方形の面積は {{ calc }} cm2</div>
</template>
```

```:出力結果
・ボタン押下前
幅 1 cmと高さ 2 cmの長方形の面積は 2 cm2

・ボタン押下後
幅 2 cmと高さ 2 cmの長方形の面積は 4 cm2
```

## 補足
計算を実行する際の関数の記述方法に指定はない
以下のどれでも実行可能。

```:無名関数
const calc = computed(
	function(): number {
		return width.value * width.value
 	}
 );
```

```:アロー関数の省略型
const calc = computed(
    (): number => width.value * width.value
);
```

# ウォッチャー
算出プロパティは非同期処理のような重い処理には不向きのため、そのような場合にウォッチャーで処理を実行する。
ウォッチャーはリアクティブ変数の値の変化に応じて特定の処理を実行するための仕組み。

## wacthEffect
watchEffect()関数は、引数としてコールバック関数を受け取り、コールバック関数の内部にはリアクティブ変数が変化したときに実行する処理を記述する。
Vueは、このコールバック関数内で利用されている全てのリアクティブ変数を監視しており、それらのどれかひとつでも値が変更されると、コールバック関数を実行する。

```:記法
watchEffect(
    (): void => { 
        リアクティブ変数に応じて実行される処理  // コールバック関数
    } 
);
```


## watch
watch()関数は第1引数に監視対象のリアクティブ変数を指定し、第2引数にコールバック関数を渡す。

```:記法
watch(監視対象リアクティブ変数,
    (): void => {
        監視対象が変化した際に実行される処理  // コールバック関数
    }
);
```

### 即時実行のwatch
watch()はwatchEffect()と違い初回起動時にコールバック関数を実行しない。
watch()で初回起動時にコールバック関数を実行する方法は、第3引数に{immediate: true}オプションを指定すること。

```:記法
watch(監視対象リアクティブ変数,
    (): void => {
        監視対象が変化した際に実行される処理  // コールバック関数
    },
{immediate: true}
);
```

### 変更前後の値を利用する場合のwaatch()
watch()は監視対象変数の値が変化した際、新旧それぞれの値を引数として受け取れる。
コールバック関数の第1引数に監視対象のリアクティブ変数、第2引数に以前の値を指定することで自動的に値が渡される

```:記法
watch(監視対象リアクティブ変数,
    (newVal: データ型, oldVal:データ 型): void => {
        監視対象が変化した際に実行される処理  // コールバック関数でOK
    }
);
```

## watchEffectとwatchのまとめ
watch()はwatchEffect()と違い初回起動時にコールバック関数を実行しない。
watchEffect()の場合は、初回起動時からコールバック関数が実行されるため起動時から情報が取得される。
watch()は監視対象の値が変化する前と後の値を引数に受け取れる。

<table>
	<tr>
		<td></td>
		<td>watchEffect</td>
		<td>watch</td>
	</tr>
	<tr>
		<td>監視対象</td>
		<td>コールバック内の全てのリアクティブ変数</td>
		<td>指定のリアクティブ変数</td>
	</tr>
	<tr>
		<td>実行開始のタイミング</td>
		<td>起動時</td>
    		<td>対象のリアクティブ変数に変化が発生してから<br>（第三引数により起動に実行可能）</td>
	</tr>
	<tr>
		<td>変化前後の値の利用</td>
		<td>不可</td>
		<td>可能</td>
	</tr>

</table>