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
320
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
今だからこそ入門する Server-Sent Events (SSE)
nearme_tech
PRO
3
240
Rancher と Terraform
fufuhu
2
550
パッケージ設計の黒魔術/Kyoto.go#63
lufia
3
440
Navigation 2 を 3 に移行する(予定)ためにやったこと
yokomii
0
320
楽して成果を出すためのセルフリソース管理
clipnote
0
170
複雑なフォームに立ち向かう Next.js の技術選定
macchiitaka
2
170
もうちょっといいRubyプロファイラを作りたい (2025)
osyoyu
1
450
Android端末で実現するオンデバイスLLM 2025
masayukisuda
1
160
複雑なドメインに挑む.pdf
yukisakai1225
5
1.2k
プロポーザル駆動学習 / Proposal-Driven Learning
mackey0225
2
1.3k
CJK and Unicode From a PHP Committer
youkidearitai
PRO
0
110
2025 年のコーディングエージェントの現在地とエンジニアの仕事の変化について
azukiazusa1
24
12k
Featured
See All Featured
Fashionably flexible responsive web design (full day workshop)
malarkey
407
66k
The World Runs on Bad Software
bkeepers
PRO
70
11k
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
194
16k
Fireside Chat
paigeccino
39
3.6k
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
252
21k
Site-Speed That Sticks
csswizardry
10
820
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
31
2.2k
The Straight Up "How To Draw Better" Workshop
denniskardys
236
140k
How to Create Impact in a Changing Tech Landscape [PerfNow 2023]
tammyeverts
53
2.9k
Code Review Best Practice
trishagee
70
19k
RailsConf 2023
tenderlove
30
1.2k
For a Future-Friendly Web
brad_frost
180
9.9k
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オブジェクトや関数の返 す値が変更されたことを検知してコールバックを実行することができる
ありがとうございました。 質問などあればどうぞ!