Mar 18, 2022
6 mins read
Vue.jsを使用する際にwatchを使う頻度はそこまで多くなく、使う度にドキュメントを確認するので、記事にまとめておく。
Vue3のwatch
とwatchEffect
の仕様をまとめていく。また、それぞれの違いもまとめる。
指定したデータを監視して、変化があればコールバック関数が実行する。
単一のデータ監視と複数のデータ監視の2種類の使い方が存在する。
const count = ref(0)
// 第一引数に監視したいデータを記載する
watch(count, (newCount, prevCount) => {
/* ... */
})
const state = reactive({
count: 0
})
// 第一引数に監視したいデータをコールバック関数で記載する
watch(() => state.count, (newCount, prevCount) => {
/* ... */
}
)
const firstName = ref('')
const lastName = ref('')
// 第一引数を配列にしている
watch([firstName, lastName], (newValues, prevValues) => {
console.log(newValues, prevValues)
})
firstName.value = 'John' // logs: ["John", ""] ["", ""]
lastName.value = 'Smith' // logs: ["John", "Smith"] ["John", ""]
複数のデータを監視し、両方のデータの検知をしたいときには、nextTick
などを使用する
const changeValues = async () => {
firstName.value = 'John' // logs: ["John", ""] ["", ""]
await nextTick()
lastName.value = 'Smith' // logs: ["John", "Smith"] ["John", ""]
}
アクティブな配列やオブジェクトの値を検知するには、値のコピーを作成する必要がある。また、コールバック関数で記載する。
const numbers = reactive([1, 2, 3, 4])
// スプレッド構文で展開する必要がある
watch(() => [...numbers], (numbers, prevNumbers) => {
console.log(numbers, prevNumbers)
}
)
numbers.push(5) // logs: [1,2,3,4,5] [1,2,3,4]
深くネストしたときには、deep
を利用する
watch(() => state, (state, prevState) => {
console.log('deep', state.attributes.name, prevState.attributes.name)
},
{ deep: true }
)
しかし、deep
を使った時には、現在値と前回値の取得ができなくなることがあるため、完全に監視するときにはライブラリを利用する
import _ from 'lodash'
const state = reactive({
id: 1,
attributes: {
name: ''
}
})
watch(() => _.cloneDeep(state), (state, prevState) => {
console.log(state.attributes.name, prevState.attributes.name)
}
)
state.attributes.name = 'Alex'; // Logs: "Alex" ""
watchEffect
関数内のリアクティブオブジェクト(ref
, reactive
)を監視し、変更されるたびに即座に関数を再実行する。const count = ref(0)
// count(ref)が存在するため、変更した時にはコールバック関数が実行される
watchEffect(() => console.log(count.value))
// -> logs 0
setTimeout(() => {
count.value++
// -> logs 1
}, 100)
watch |
watchEffect |
|
---|---|---|
定義の仕方 | 監視対象のデータを第一引数に指定 | 関数内のリアクティブオブジェクト(ref , reactive )が監視対象 |
データの取得 | 変更前と変更後のデータが取得できる | 取得できない |
初回実行のタイミング | 定義に実行されない | 定義時に実行する |
どちらを使用するかは意見が別れるとこだとは思うが、個人的には監視する対象を明示的にしておきたいので、watch
の方が好みだと感じた。
公式ドキュメント
Qita: Vue 3 の Composition API における watch vs watchEffect