✍️

Vue3 DOMの変更を検知して処理を行いたい時についてまとめる

2023/08/25に公開

onMounted()

コンポーネントがマウントされた後に呼び出されるコールバックを登録します。

Vue3を利用したプロジェクトでは(Nuxtでも同様に) onMouted()で処理をすることが多々あると思います。そこでは文字通りコンポーネントがマウントされた時に行いたい処理を記述します。
例えば、APIからデータをフェッチしておいて、コンポーネントで描画する。

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

const fetchedData = ref()

onMounted(() => {
   axios.get(`http://nanikasirano-api`).then((res) => {
   	console.log('res', res)
	fetchedData.value = res.data
   }).catch(err => {
	console.log('err', err)
   })
})
</script>

<template>
  <div>{{ fetchedData }}</div>
</template>

onUpdated()

コンポーネントがリアクティブな状態変更によって DOM ツリーを更新した後に呼び出されるコールバックを登録します。

onUpdatedの場合は、マウント時ではなくDOMツリーが更新した後に処理が行われるので
DOMに何らかの更新があった際に行いたい処理を記述します。
例えば、クリックイベントでcount変数に変更があった時、別の変数updatedCountもそれに応じて処理を加える

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

const count = ref(0)
const updatedCount = ref(0)


onUpdated(() => {
  // テキストの内容は、現在の `count.value` と同じでしょう
  console.log(document.getElementById('count').textContent)
  updatedCount.value = document.getElementById('count').textContent 
  updatedCount.value++
})
</script>

<template>
  <button id="count" @click="count++">{{ count }}</button>
</template>

この場合はupdatedCountにDOMから取得したcountの値を入れ、+1する処理をしているので
updatedCountは常にcountの+1した値になる

onUpdatedの注意点として、無限ループを引き起こす可能性があるため、データ変更時に無限ループに陥らないように注意することが重要です。

他にも値の変更を検知して、変更に応じた処理をしたいときはウォッチャー (Watcher) を利用することもできます

ウォッチャー(watch)

watch 関数 を使用することでリアクティブな状態の一部が変更されるたびにコールバックを実行することができます

watch(
  () => obj.count,
  (count) => {
    console.log(`count is: ${count}`)
  }
)

nextTick()

特定の状態変更の後に更新された DOM へアクセスする必要がある場合は、代わりに nextTick() を使用してください。

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

const count = ref(0)

function onClick() {
  // DOM はまだ更新されていない
  const fetchedData = fetchSomeData()
  nextTick()
  // ここでは DOM が更新されている
  scrollToTargetPlace('#scrollToHere')
}
</script>

<template>
  <button @click="onClick">ボタン</button>
  
  <div v-if="fetchedData">
    <div id="scrollToHere"></div>
  </div>
</template>

このコードではonClickイベント時にスクロールさせたいけど、DOMの描画を待ってからでないとDOMが生成されてないのでスクロールできない場合に利用しています。スクロールの場合、処理のタイミングによってはうまく動作しないことがあるのでこの関数でうまくタイミングを調整することで適切なタイミングでイベントを発生させることができます。

いずれの関数もDOMの状態を細かく検知して処理を行うことができるので非常に便利です。

参考文献

https://ja.vuejs.org/api/composition-api-lifecycle.html

Discussion