前提知識
vueやref、watchについて知識ある人は本文まで読み飛ばしてください。
リアクティビティとは
Vueのリアクティビティシステムは、データの変更を検知し、それに応じてUIを自動更新します。
これにより、データとUIの一貫性が保たれ、開発者はデータの管理に集中できます。
refとは
Vue 3で導入されたref
は、値をリアクティブにするための関数です。
これにより、値の変更がVueシステムによって追跡され、関連するUIが更新されます。
ウォッチャーとは
ウォッチャーは、データや状態の変更を監視し、変更があった際にカスタムの副作用やロジックを実行する機能です。
watchとは
watch
はVueにおいてウォッチャーを作成するVueのAPIです。
これにより、指定したデータソースの変更を監視し、変更があった際にコールバック関数を実行します。
サンプルコード
<script setup lang="ts">
import { ref, watch } from 'vue';
// refを使ってリアクティブなカウンターを作成
const count = ref(0);
// watchを使ってcountの変更を監視
watch(count, (newValue, oldValue) => {
// カウンターが変更されたときにコンソールにログを出力
console.log(`カウントが ${oldValue} から ${newValue} に変更されました。`);
});
// カウンターを増加させる関数
const increment = () => {
count.value++;
};
</script>
<template>
<div>
<p>カウント: {{ count }}</p>
<button @click="increment">増加</button>
</div>
</template>
この例では、countはrefを使用して作成されたリアクティブな値です。
count.valueの値が変わると、Vueのリアクティビティシステムがこれを検知し、関連するUI部分を自動的に更新します。
また、watchはcountの変更を監視し、変更があるたびにコールバック関数を実行して、変更をコンソールにログ出力します。
これにより、Vueのリアクティビティシステムの動作原理を理解するのに役立ちます。
本文
vue3において親要素から渡したpropsの値を下記のようにwatchしようとしたら、値の変更が検知されなかった。
<script setup lang="ts">
watch(props.selectedSiteJsUrls, (newUrls, oldUrls) => {
// ここには配列が変更されたときに実行するコードを書きます。
console.log('新しいURLリスト:', newUrls);
console.log('古いURLリスト:', oldUrls);
});
</script>
下記のようにアロー関数で渡し、deep:true
をつけると、値の変更が検知され、consoleが呼ばれるようになる
<script setup lang="ts">
watch(() => props.selectedSiteJsUrls, (newUrls, oldUrls) => {
console.log('新しいURLリスト:', newUrls);
console.log('古いURLリスト:', oldUrls);
}, { deep: true });
</script>
chatgpt先生による解説
Vue 3のリアクティブシステムにおいて、アロー関数を使用してプロパティをラップする理由は
Vueが内部的にリアクティブな依存関係を追跡する方法に関連しています。
直接的にpropsのプロパティをwatchに渡す場合(例:watch(props.selectedSiteJsUrls, callback))と
アロー関数を使用する場合(例:watch(() => props.selectedSiteJsUrls, callback))の違いを理解することが重要です。
アロー関数の使用
- リアクティブな依存関係の設定: Vueのリアクティブシステムは、アロー関数内でアクセスされるプロパティを「依存関係」として認識し、これらのプロパティが変更されたときに関連するリアクティブな効果(この場合はwatchコールバック)をトリガーします。
- 値の変更の追跡: アロー関数内でプロパティにアクセスすることにより、Vueはそのプロパティの値が変更された場合にのみ、watchコールバックを実行するように設定します。これにより、プロパティの値そのものの変更をより正確に追跡できます。
- より細かい制御: アロー関数を使用することで、プロパティの特定の部分(例えば、オブジェクトの特定のキー)だけを監視するように設定することが可能になります。これは、より細かく監視の範囲を制御するのに役立ちます。
直接propsを渡す場合
- リファレンスの変更のみの追跡: 直接propsのプロパティをwatchに渡すと、Vueはそのプロパティのリファレンス(参照)が変更された場合にのみ反応します。つまり、配列やオブジェクトの中身が変わっても、そのリファレンスが同じであれば、変更は検知されません。
- 深い監視(deepオプション)の必要性: リファレンス型のデータ(例:オブジェクトや配列)の内容が変更された場合にこれを検知するためには、deepオプションを設定する必要があります。
結論 - アロー関数を使用してプロパティをラップすることにより、Vueはそのプロパティの現在の値の変更を追跡し、変更があった場合にのみリアクティブな効果(watchコールバック)をトリガーします。これにより、より正確に、かつ細かくプロパティの変更を検知することができます。
deep:trueに関して
Vue 3において、アロー関数を使用してwatchを設定する場合、deep: trueオプションの必要性は、監視対象のデータの種類に依存します。具体的には:
-
プリミティブ値(文字列、数値、ブーリアンなど):これらの値に対しては、deep: trueは必要ありません。プリミティブ値の変更は、Vueのリアクティブシステムによって自動的に検知されます。
-
オブジェクトや配列:これらのリファレンス型のデータに対してwatchを使う場合、deep: trueオプションが重要になることがあります。deep: trueを設定すると、Vueはオブジェクトや配列の内部の変更(プロパティの追加/削除や配列の要素の変更など)も検知します。
例えば、props.selectedSiteJsUrlsが配列である場合、この配列内の要素が変更されたときにそれを検知したいなら、deep: trueオプションが必要です。