Vue.js

Vue3|refとreactiveの理解<表側と少し裏側>

kazuki.m
kazuki.m

Vueの基本であるリアクティビティーを理解したい

リアクティブ

まずはざっくり理解するところ

・値が変更があったときに、画面に表示される内容も変更される

・画面に表示される内容が変更されたら、値も変更される

ユーザーからすれば当たり前すぎることですが、Vueはリアクティブで実現できます。ありがたい・・・

サンプル

今回はリアティブを支えるrefとreactiveについて、簡易なサンプルコードで以下の点を試してみました

・ref()とreactive()にプリミティブ値を使ってみる

・ref()とreactive()にオブジェクト値を使ってみる

・ref()をreactive()に使ってみる

検証結果

サンプルコードで試した結果、次のような結果が得られました。

・ref()にはプリミティブ値もオブジェクト値も使える

・reactive()にはプリミティブ値を入れても、きちんとリアクティブにならない。(遅延して値は反映される。この点は、なぜ??)

・ref()にオブジェクト値を入れても、template側はvalueが不要になるのでreactive()と同じ使用感になる。(勿論script側ではvalueが必要)

・reactive()のオブジェクトにref()を入れると、お互いが更新される。(reactive.xxxでもref.valueでもお互いが更新される)

・reactive()にref()を入れても、valueは不要(勝手アンラップしてくれる。)

以上を踏まえるとref()とreactive()の関係は、ref()はvalueというkeyにした値をreactive()にしているイメージ。

まだまだ曖昧なので少し裏側のソースコードも覗いてみます。

裏側のソースコード

こちらVueのリアクティブ部分のソースコードリンクです。

https://github.com/vuejs/core/blob/main/packages/reactivity/src/ref.ts#L124

https://github.com/vuejs/core/blob/main/packages/reactivity/src/reactive.ts#L406

今回は、ざっくりref()のソースコードを追ってみたいと思います。

内部ではcreateRef()でref()を作っているっぽいので、次はcreateRefを見てみます。

createRef()は RefImpl()を生成しているので、次はRefImplを見てみます。

RefImplはgetterとsetterでvalueの取得(trakRefValue)と更新(triggerRefValue)をしています。

この先のtrackとtriggerでDOMへ反映する処理(Effect)があるっぽいので、後日改めて追ってみたいです。

もう一点、this._valueはtoReactive()にも流れているので、こちらを見てみます。

toReactiveですが、どうやらvalueの値がオブジェクト値か判定してオブジェクト値ならreactive()に入れています。

なのでref()にオブジェクト値を入れてもリアクティブだったのは、この処理が理由でした。

公式ガイドでは、Proxy はリアクティブオブジェクトに、getter / setters は ref に使用。と言及されていますが、

この点はもう少し理解したいです。

https://ja.vuejs.org/guide/extras/reactivity-in-depth.html#how-reactivity-works-in-vue

今回はリアクティブの表面を少しだけ覗いてみましたが、裏側の処理も追いかけていくと勉強になりました。

refとreactiveが互いに独立の機能ではなく、お互いが密接に関係している機能であることも伺えました。

リアクティブについては、今後もサクッとコードを書いて試したり、ソースコードの理解をしていきたいと思います。

  • この記事を書いた人

kazuki.m

エンジニア

開発言語:Python、Typescript

最近の関心:Vue、Typescript、Rust

-Vue.js