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
360
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
CSC307 Lecture 14
javiergs
PRO
0
470
安いハードウェアでVulkan
fadis
0
270
クライアントワークでSREをするということ。あるいは事業会社におけるSREと同じこと・違うこと
nnaka2992
1
350
Docコメントで始める簡単ガードレール
keisukeikeda
1
120
米国のサイバーセキュリティタイムラインと見る Goの暗号パッケージの進化
tomtwinkle
2
600
最初からAWS CDKで技術検証してもいいんじゃない?
akihisaikeda
4
160
Claude Codeログ基盤の構築
giginet
PRO
7
3.4k
Claude Code Skill入門
mayahoney
0
400
maplibre-gl-layers - 地図に移動体たくさん表示したい
kekyo
PRO
0
290
ロボットのための工場に灯りは要らない
watany
10
2.9k
OTP を自動で入力する裏技
megabitsenmzq
0
110
Angular-Apps smarter machen mit Gen AI: Lokal und offlinefähig - Hands-on Workshop!
christianliebel
PRO
0
120
Featured
See All Featured
Statistics for Hackers
jakevdp
799
230k
Introduction to Domain-Driven Design and Collaborative software design
baasie
1
640
Lightning Talk: Beautiful Slides for Beginners
inesmontani
PRO
1
480
Measuring Dark Social's Impact On Conversion and Attribution
stephenakadiri
1
160
Build The Right Thing And Hit Your Dates
maggiecrowley
39
3.1k
How STYLIGHT went responsive
nonsquared
100
6k
30 Presentation Tips
portentint
PRO
1
250
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
659
61k
AI Search: Implications for SEO and How to Move Forward - #ShenzhenSEOConference
aleyda
1
1.2k
DevOps and Value Stream Thinking: Enabling flow, efficiency and business value
helenjbeal
1
150
Visualization
eitanlees
150
17k
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
38
2.8k
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オブジェクトや関数の返 す値が変更されたことを検知してコールバックを実行することができる
ありがとうございました。 質問などあればどうぞ!