Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Vue.jsのreactive周りの仕組みをコードを読んで理解してみる
Search
Kaido Iwamoto
March 15, 2024
Programming
1
350
Vue.jsのreactive周りの仕組みをコードを読んで理解してみる
Kaido Iwamoto
March 15, 2024
Tweet
Share
More Decks by Kaido Iwamoto
See All by Kaido Iwamoto
Kotlin ことはじめ
odiak
1
290
Other Decks in Programming
See All in Programming
AtCoder Conference 2025「LLM時代のAHC」
imjk
2
640
Context is King? 〜Verifiability時代とコンテキスト設計 / Beyond "Context is King"
rkaga
10
1.5k
ZJIT: The Ruby 4 JIT Compiler / Ruby Release 30th Anniversary Party
k0kubun
1
310
The Art of Re-Architecture - Droidcon India 2025
siddroid
0
160
[AtCoder Conference 2025] LLMを使った業務AHCの上⼿な解き⽅
terryu16
6
1k
AI 駆動開発ライフサイクル(AI-DLC):ソフトウェアエンジニアリングの再構築 / AI-DLC Introduction
kanamasa
11
4.8k
LLMで複雑な検索条件アセットから脱却する!! 生成的検索インタフェースの設計論
po3rin
4
1.1k
React 19でつくる「気持ちいいUI」- 楽観的UIのすすめ
himorishige
11
2.9k
Patterns of Patterns
denyspoltorak
0
410
gunshi
kazupon
1
130
脳の「省エネモード」をデバッグする ~System 1(直感)と System 2(論理)の切り替え~
panda728
PRO
0
130
Go コードベースの構成と AI コンテキスト定義
andpad
0
150
Featured
See All Featured
Raft: Consensus for Rubyists
vanstee
141
7.3k
The Spectacular Lies of Maps
axbom
PRO
1
410
SEO Brein meetup: CTRL+C is not how to scale international SEO
lindahogenes
0
2.3k
Marketing Yourself as an Engineer | Alaka | Gurzu
gurzu
0
110
What Being in a Rock Band Can Teach Us About Real World SEO
427marketing
0
160
Digital Ethics as a Driver of Design Innovation
axbom
PRO
0
140
The B2B funnel & how to create a winning content strategy
katarinadahlin
PRO
0
220
The Curse of the Amulet
leimatthew05
0
6.7k
The Language of Interfaces
destraynor
162
26k
Practical Orchestrator
shlominoach
190
11k
Game over? The fight for quality and originality in the time of robots
wayneb77
1
73
Agile that works and the tools we love
rasmusluckow
331
21k
Transcript
Vue.jsのreactive周りの仕組みをコードを読んで理解して みる
自己紹介 岩本海童 フロントエンドエンジニア Android、サーバーサイドは経験はあるが、最近は趣味で触る程度 React, TypeScriptが得意 去年からVue.jsを初めて仕事で使い始めた
宣伝:趣味で作っているサービスなど Kakeru (https://about.kakeru.app) ブラウザで動く共同編集もできる手書きメモのアプリ 炭水化物量計算くん (https://carbs-calc.pages.dev) 食材とその量を入力して炭水化物量を計算する
本題: Vue.jsのreactiveってどういう仕組みなの? Reactに慣れていると、なんかとても便利で不思議な仕組み 使っていておおよそ仕組みはイメージできるけど、ちゃんとコード読んで確かめたい
かなり雑で、一部のケースを読み飛ばしたりしています。指摘や質問など大歓迎です。
どこから始める? リポジトリ: vuejs/core とりあえず ref() と reactive() 初心者「ほぼ同じでしょ?」 あとは、それらの変更を検知する側である watch()
computed() はたぶん仕組みが同じなので今回はパス
定義場所を探す ref() : packages/reactivity/src/ref.ts reactive() : packages/reactivity/src/ref.ts watch() : packages/runtime-core/src/apiWatch.ts
ref編
ref 関数 createRefを呼んでいるだけ(shallow: false) createRef 関数 new RefImpl()してるだけ
RefImpl クラス (1) valueプロパティのgetter/setterがある _value に toReactive() した値 オブジェクトなら reactive()
でラップ、それ以外はそのまま _rawValue に toRaw() した値 値がreactiveならアンラップしたもの
RefImpl クラス (2) getter trackRefValue を呼ぶ _value を返す setter toRawした新しい値を
_rawValue と比較する 変化していれば、 _value と _rawValue に代入し、 triggerRefValue を呼ぶ
事前知識: ReactiveEffectについて watchやcomputedなどの内部で使われる、reactiveな値が変化した時に実行される処理 のかたまりのようなものです(雑な理解) 参照されたreactiveな値が変化したかどうかのフラグを持つ
runメソッドが呼ばれると、引数で渡された関数(fn)を実行する その際に、関数の内部で参照されたreactiveな値をトラッキングするための準備や その後の後片付けなどを行う 現在実行中のReactiveEffectがモジュールの変数に入っていて、trackEffect関数か ら参照できる triggerやschedulerという引数で与えられた関数が間接的にrunメソッドを呼ぶことにな る
trackRefValue 関数 Refオブジェクトに dep?: Map<ReactiveEffect, number> というプロパティがある キーはRefを参照しているReactiveEffectで、値は何回目の実行か( _trackId )
一方、ReactiveEffectはdepsというプロパティにdepの配列を持っている depがundefinedなら初期化する trackEffect を呼んで現在実行中のReactiveEffectに値が参照されたことを知らせる
trackEffect 関数 (reactive関数の方でも呼ばれる共通のやつ) depsに現在実行中のReactiveEffectとその _trackId をセットする( _trackId につい ては省略) 場合によっては、前の実行のcleanup処理などを行うが、詳細は省略(お茶をにごす)
triggerRefValue 関数 triggerEffect を呼んで、参照しているReactiveEffectに値の変更を通知する triggerEffect 関数 (reactive関数の方でも呼ばれる共通のやつ) RefオブジェクトのdepにのキーになっているReactiveEffectたちの処理を呼び起こす
ref 編 終わり valueが参照されたら参照を記録し、valueが変更されたら変更を通知するという割と素 朴な仕組み (deps周りの処理は少し複雑だけど)
reactive 編(1) 長くなりそうなので手短に refがvalueプロパティを持つオブジェクト(RefImpl)を返したのに対して、こちらはProxy を返します Proxyはプロパティのget/set、関数呼び出しなどをフックできる 与えられたオブジェクトをラップして、元のオブジェクトそっくりに振る舞いなが ら参照や変更を監視する Refと同様にdepプロパティを持っている
reactive 編(2) プロパティのgetが呼ばれた場合... trackEffect を呼び出してReactiveEffectに参照を通知する(depを更新する) オブジェクト本体のプロパティの値を toReactive して返す プロパティのsetが呼ばれた場合 triggerEffectを呼び出してReactiveEffectを呼び起こす
オブジェクト本体のプロパティの値を更新する
(終わり)(短い)
watch 編 doWatch 関数が本体
doWatch 関数(1) 第1引数はいくつかのパターンがあるが、どのパターンも関数でラップされて getter と なる oldValue変数で最後に実行したgetterの戻り値を持っておく job 関数 effectがdirtyなら、effectを実行する(getterの戻り値が返ってくる)
前回から値が変化していれば、コールバックを実行する scheduler 関数 job を次のマイクロタスクで実行する
doWatch 関数(2) effect = ReactiveEffect(getter, NOOP, scheduler) でReactiveEffectを初期化 する unwatch
関数 effectのstopを呼んで無効化する immediateオプションがtrueの場合はeffectを実行して結果をoldValueに入れておく 実行するとscheduler→job→コールバックの流れで呼ばれる unwatchを返す
まとめ
ReactiveEffectというクラスで、関数内で参照されたreactive系のオブジェクトをトラッ キングし、変更された際に通知を受けるとことができる ref関数やreactive関数が返すオブジェクトは、ReactiveEffectからアクセスされると参照 が記録され、変更されるとReactiveEffectに通知される watch関数はReactiveEffectを使って、与えられたref/reactiveオブジェクトや関数の返 す値が変更されたことを検知してコールバックを実行することができる
ありがとうございました。 質問などあればどうぞ!