Vue3のrefにObjectが代入されると、reactiveでwrapされるらしいのでコードを読む
Vue3のrefにObjectが代入されると、reactiveでwrapされるらしいのでコードを読む
こんにちは、合同会社Stegの@keigoです。
Vue3の ref()
関数は、Objectが代入するとその値をreactive()
でwrapするらしいです。
参考:https://ja.vuejs.org/api/reactivity-core.html#ref
本当にそうなの?というのが気になったので、コードを読んでみました。
コードを読んでいく
vuejs/core
のリポジトリの、reactive.tsのコードを読んでいきます。
記事執筆時点では、以下のようなコードになっています。
export const toReactive = <T extends unknown>(value: T): T =>
isObject(value) ? reactive(value) : value
こちらは、toReactive
関数の引数に来たvalue
という変数がObjectである場合は、reactive
でwrapしています。
ではこのtoReactive
関数は、ref
関数が呼び出された時にどのように発火するのでしょうか。
1. ref関数の実装
ref
関数の処理は、ref.tsに記述されています。
記事執筆時点では、以下のようなコードになっていました。
export function ref(value?: unknown) {
return createRef(value, false)
}
createRef
関数が呼び出されているのがわかります。
2. createRef関数の実装
createRef関数の実装は、以下のようになっていました。
function createRef(rawValue: unknown, shallow: boolean) {
if (isRef(rawValue)) {
return rawValue
}
return new RefImpl(rawValue, shallow)
}
RefImpl
クラスが呼び出されているのがわかります。
3. RefImplクラスの実装
RefImplクラスの実装は、以下のようになっていました。
class RefImpl<T> {
private _value: T
private _rawValue: T
public dep?: Dep = undefined
public readonly __v_isRef = true
constructor(value: T, public readonly __v_isShallow: boolean) {
this._rawValue = __v_isShallow ? value : toRaw(value)
this._value = __v_isShallow ? value : toReactive(value)
}
...
コンストラクタにて、toReactiveが呼び出されています。
記述されている三項演算子は、以下のような条件になっています。
__v_isShallow
という変数がtrueの場合はvalue
が代入される。falseの場合はtoReactive
の返り値が代入される。
__v_isShallow
という変数は、コンストラクタ実行次にreturn createRef(value, false)
という呼び出し方をされているので、false
が代入されます。
したがって、toReactive
の関数が発火しています。
まとめ
Vue3のref
関数にObjectを代入すると、reactive
関数でwrapされることがわかりました。便利ですね。