今更ですが、Oject.freeze()を使用することで再描画を防ぐテクニックがあることを知ったのでメモします。
(Vueを想定したコードにしています)
<template>
<div>
<p>名前: {{ human.name }}</p>
<button @click="changeName">名前を変更?</button>
</div>
</template>
<script setup>
import { ref } from 'vue';
const human = ref(Object.freeze({
name: '田中太郎',
age: 25
}));
const changeName() {
human.name = '田中次郎'; // ここでTypeError: Cannot assign to read only property 'name' of objectが発生
}
</script>
Object.freezze()で囲んだオブジェクトは凍結されます。
凍結されたオブジェクトは、プロパティの上書きや追加、削除をすることができなくなります。
Object.freeze()を使用したオブジェクトのプロパティの値を変更しようとした場合、TypeErrorが発生するようになります。
(ただ、MDNに以下の一文があったので、エラーが出ない(静かな)場合もある?)
これを行おうとすると、静かに、あるいは TypeError 例外が発生し、失敗します(厳格モードの場合によく発生しますが、これに限ったことではありません)。
値を固定することで、その値を使用している要素の再描画を防ぐ わけですね。
例では小さいオブジェクトでしたが、実際はもっと大きなオブジェクトを固定しておくことが多いと思います。
これに対する唯一の例外は、既存のプロパティの変更を防ぐ Object.freeze()の使用です。これはリアクティブシステムが変更を 追跡 することができないことも意味します。
引用元:https://v2.ja.vuejs.org/v2/guide/instance
Vue2公式でも、このObject.freeze()によってリアクティブな追跡を防ぐ方法が紹介されていました。
ただ、Vue3が標準となった今はもっと良い書き方がありそうです。
こちらの記事では、Vue3のリアクティビティーAPIのshallowRef, trrigerRef, effectScopeが紹介されていました(掲載してくださった方ありがとうございます)。
https://speakerdeck.com/hal_spidernight/vue3no-bu-ta-miip-ndapahuomansutiyuningu2024?slide=17
それぞれ、
- ref()の浅いバージョンであるshallowRef
- shallowRefを強制発火させるtriggerRef
- watchやcomputedを監視して、一括で廃棄することもできるeffectScope
といった機能のようです。
こちらの方がObject.freeze()より柔軟に対応できそうなので、Vue3においてはリアクティビティーAPIを使用するのが今風の書き方なのかもしれませんね。