Vue.jsのnextTickについて
状態を変更した直後に nextTick()
を使用すると、DOM 更新が完了するのを待つことができます。 引数としてコールバックを渡すか、戻り値の Promise を使用できます。
例
<script setup>
import { ref, nextTick } from 'vue'
const count = ref(0)
async function increment() {
count.value++
// DOM はまだ更新されていない
console.log(document.getElementById('counter').textContent) // 0
await nextTick()
// ここでは DOM が更新されている
console.log(document.getElementById('counter').textContent) // 1
}
</script>
<template>
<button id="counter" @click="increment">{{ count }}</button>
</template>
上記は公式ドキュメントから引用
実サンプル
バーコードのライブラリを使って会員IDをバーコードで表示した時の例です。
注意:不要な箇所は省略してます
<template>
<div>
<img ref="barcodeRef" alt="" src="" />
</div>
</template>
<script lang="ts">
import JsBarcode from 'jsbarcode'
const barcodeRef = ref(null)
watch(
() => props.barcodeId,
() => {
nextTick(() => {
if (barcodeRef.value && props.barcodeId) {
JsBarcode(barcodeRef.value, props.barcodeId, {
format: 'CODE128',
lineColor: '#000000',
width: 2,
height: 50,
fontSize: 15,
textMargin: 2,
displayValue: true,
})
}
})
},
{ immediate: true },
)
</script>
nextTickを使わなくても問題なく表示されるのですが、別のコンポーネントを開いて、閉じた際にバーコードが表示されなくなるケースもありました。
原因はbarcodeRef.value
がnull
の状態でwatchが動いてしまう為。
再マウント時に DOM が揃った後に処理するできるようにnextTickを使うことで防ぐことができました。
公式ではnextTick()した後にDOMが更新後の処理を書いてますが、DOM更新後の処理をコールバック関数として引数に渡してもOKです。
// 以下どちらも同じ
await nextTick()
// DOMが更新後の処理をnextTick実行後に書く
await nextTick(() => {
// DOMが更新後の処理をコールバック関数内に書く
})