「v-memo」と「v-once」によって解決できる問題
Vueは、大きく以下のような手順で再レンダリングをしています。
-
データの変更
OptionsAPIで言うところのdata、CompositionAPIで言うところのrefやreactiveなどのデータオブジェクトが変更されると、その変更が検出されます。 -
仮想DOMの生成
新しい「仮想DOM」を生成します。仮想DOMは、実際のDOMの軽量コピーで、どこが変更されたかを効率的に計算するために使用されます。 -
差分計算
(2)で生成された新しい仮想DOMと、その前に生成された仮想DOMを比較して、どの部分が変更されたかを計算します。 -
DOMの更新
(3)にて算出した差分を、実際のDOMに対して適用します。(このプロセスは「patch」、「diffing」、「reconciliation」とも呼ばれています)
DOMはツリー状で形成されます。親にあたる要素が再レンダリングされた場合、その子要素も一緒に再レンダリングされてしまいます。
子要素に多くの要素を含む場合、この不要な再レンダリングがパフォーマンスの低下に繋がることがあります。
このような、不要な再レンダリングを制御する為に使用されるのが、今回紹介する「v-once」と「v-memo」です。
v-once
<template>
<h1 v-once>Welcome to my page!</h1>
</template>
v-onceは、それを適用した要素とその子要素にあたるものは全て、初回のみレンダリングを行い、再レンダリングを実行しないようにすることができるディレクティブです。
たとえ依存するデータが変更されたとしても、再レンダリングは実行されないので表示は更新されません。
使い所としては、「refやreactiveなどのデータ更新によって再レンダリングされる必要のない要素」に対して適用します。
v-memo
<template>
<div v-memo="[valueA, valueB]">
...
</div>
</template>
無条件で再レンダリングをさせないv-onceに対して、再レンダリングに条件をつけられるのが、バージョン3.2より利用可能になったv-memoです。
指定された配列内のデータが更新された場合にのみ、再レンダリングを実行します。もし空配列を渡した場合は、v-onceと同様の挙動になります。
大きなコンポーネントの再レンダリングをコントロールするのに便利です。
使い所としては、以下のようなv-forを用いて作成されたリストに対して使用します。
<div v-for="item in items" :key="item.id" v-memo="[items]">>
<p>{{ item.id }}: {{ item.name }}</p>
</div>
公式ドキュメントによるとv-memoは、1000件を超えるリストに対して使用すると効果を発揮するそうです。
あまり1000件を超えるリストを扱うことは無さそうですが、もし膨大な量のリストを扱う際にはv-memoの利用を検討してみてください。
v-memo は、パフォーマンスが重要なシナリオでのミクロな最適化を行うためにのみ提供されており、ほとんど必要ありません。この機能が役に立つ最も一般的なケースは、大きな v-for リスト(length > 1000)をレンダリングするときです
v-forと併用する際には、v-forを付与した要素にv-memoを付与してください。以下のようにv-forの内部でv-memoを使用することはできません。
<div v-for="item in list" :key="item.id">
<p v-memo="[list]">{{ item.id }}: {{ item.name }}</p>
</div>


