はじめに
Vue3(Nuxt3/Vuetify3) を使い始めてはや半年ほど。
リアクティビティに関してそれなりに理解してはいますが、ちゃんと検証したことはありませんでした。
なので、リアクティブ関連の関数を一通り使って、雑にまとめてみました。
検証コードは下記に置いていますので、実際に動かしてみてください。
https://github.com/PGseatake/reactivity
(Nuxt3/Vuetify3 でシンプルな実装しているので、ソースを取得してテンプレートとしても使って頂けると思います)
リアクティビティ
どのような処理で画面更新が走るかをまとめています。
ref()
const val = ref(0);
val.value = 1; // 更新あり
const obj = ref({ a: 0 });
obj.value.a = 1; // 更新あり
obj.value = { a: 10 }; // 更新あり
const ary = ref([0]);
ary.value[0] = 1; // 更新あり
ary.value.push(2); // 更新あり
ary.value = [10]; // 更新あり
const objobj = ref({ obj: { a: 0 } });
objobj.value.obj.a = 1; // 更新あり
objobj.value.obj = { a: 10 }; // 更新あり
objobj.value = { obj: { a: 20 } }; // 更新あり
const aryobj = ref([{ a: 0 }]);
aryobj.value[0].a = 1; // 更新あり
aryobj.value[0] = { a: 10 }; // 更新あり
aryobj.value.push({ a: 20 }); // 更新あり
aryobj.value = [{ a: 30 }]; // 更新あり
reactive()
const val = reactive(0);
// val = 1; 実装不可
const obj = reactive({ a: 0 });
obj.a = 1; // 更新あり
// obj = { a: 10 }; 実装不可
const ary = reactive([0]);
ary[0] = 1; // 更新あり
ary.push(2); // 更新あり
// ary = [10]; 実装不可
const objobj = reactive({ obj: { a: 0 } });
objobj.obj.a = 1; // 更新あり
objobj.obj = { a: 10 }; // 更新あり
// objobj = { obj: { a: 20 } }; 実装不可
const aryobj = reactive([{ a: 0 }]);
aryobj[0].a = 1; // 更新あり
aryobj[0] = { a: 10 }; // 更新あり
aryobj.push({ a: 20 }); // 更新あり
// aryobj = [{ a: 30 }]; 実装不可
shallowRef()
const val = shallowRef(0);
val.value = 1; // 更新あり
const obj = shallowRef({ a: 0 });
obj.value.a = 1; // 更新なし
obj.value = { a: 2 }; // 更新あり
const ary = shallowRef([0]);
ary.value[0] = 1; // 更新なし
ary.value.push(2); // 更新なし
ary.value = [3]; // 更新あり
const objobj = shallowRef({ obj: { a: 0 } });
objobj.value.obj.a = 1; // 更新なし
objobj.value.obj = { a: 2 }; // 更新なし
objobj.value = { obj: { a: 3 } }; // 更新あり
const aryobj = shallowRef([{ a: 0 }]);
aryobj.value[0].a = 1; // 更新なし
aryobj.value[0] = { a: 2 }; // 更新なし
aryobj.value.push({ a: 3 }); // 更新なし
aryobj.value = [{ a: 4 }]; // 更新あり
shallowReactive()
const val = shallowReactive(0);
// val = 1; 実装不可
const obj = shallowReactive({ a: 0 });
obj.a = 1; // 更新あり
// obj = { a: 10 }; 実装不可
const ary = shallowReactive([0]);
ary[0] = 1; // 更新あり
ary.push(2); // 更新あり
// ary = [10]; 実装不可
const objobj = shallowReactive({ obj: { a: 0 } });
objobj.obj.a = 1; // 更新なし
objobj.obj = { a: 10 }; // 更新あり
// objobj = { obj: { a: 20 } }; 実装不可
const aryobj = shallowReactive([{ a: 0 }]);
aryobj[0].a = 1; // 更新なし
aryobj[0] = { a: 10 }; // 更新あり
aryobj.push({ a: 20 }); // 更新あり
// aryobj = [{ a: 30 }]; 実装不可
使いどころ
ref()
const val = ref(0); // プリミティブ値に関してはこれ一択
// 以下共通
const obj = ref({ a: 0 }); // ・変数に対して代入したい場合
const ary = ref([0]); // ・全ての値をリアクティブにしたい場合
const objobj = ref({ obj: { a: 0 } }); // ・最適化とか考えるのが面倒な時
const aryobj = ref([{ a: 0 }]);
reactive()
// 以下共通
const obj = reactive({ a: 0 }); // ・変数に対して代入が不要な場合
const ary = reactive([0]); // (変数への代入の有無が ref() との判断基準かも)
const objobj = reactive({ obj: { a: 0 } }); // ・全ての値をリアクティブにしたい場合
const aryobj = reactive([{ a: 0 }]); // ・最適化とか考えるのが面倒な時
shallowRef()
const val = shallowRef(0); // ・プロパティは変更しない場合
const obj = shallowRef({ a: 0 }); // ・更新が限定的になるので最適化時に利用
const ary = shallowRef([0]);
const objobj = shallowRef({ obj: { a: 0 } });
const aryobj = shallowRef([{ a: 0 }]);
shallowReactive()
const obj = shallowReactive({ a: 0 }); // ・ルートのプロパティだけ変更する場合
const objobj = shallowReactive({ obj: { a: 0 } }); // ・プロパティに Array/Object があっても代入で問題ない場合
const ary = shallowReactive([0]); // ・配列操作した時だけ更新したい場合
const aryobj = shallowReactive([{ a: 0 }]); // 同上