Vue.jsの中身を読んでみる (算出プロパティ1)
お仕事でVue.jsを書くことが多いのですが、なんとなく中身どうなってるんだろうって思ったので中身を読んでみることにしました。(今年はコードリーディングが目標.です..!)
Vue.jsのコード全て読もうとすると挫折しちゃいそうなので、面白そうなところ、読めそうなところつまみ食いしてみることにしました。
今回は算出プロパティのコードを読んで見ました。
算出プロパティのコードを読む
算出プロパティとは
任意に処理を含めることのできるデータ
テンプレート内にjavascriptが使用できるが、テンプレート内に多くのロジックを詰め込むと、コードが肥大化、メンテナンスが難しくなる。
<div> {{ message.split('').reverse().join('') }} </div>
複雑なロジックには算出プロパティを利用すべき
<div id="example"> <p>Original message: "{{ message }}"</p> <p>Computed reversed message: "{{ reversedMessage }}"</p> </div>
var vm = new Vue ({ el: '#example', data: { message: 'Hello' }, computed: { reversedMessage: function () { return this.message.split('').reverse().join('') } } })
console.log(vm.reversedMessage) // =\> 'olleH' vm.message = 'Goodbye' console.log(vm.reversedMessage) // =\> 'eybdooG'
算出プロパティとメソッドの違い
<p>Reversed message: "{{ reverseMessage() }}"</p>
methods: { reverseMessage: function () { return this.message.split('').reverse().join('') } }
↑上記コードで同じ結果になる。
違いは?
算出プロパティは依存関係にもとづきキャッシュされる
算出プロパティは、それが依存するものが更新されたときにだけ再評価されます。
message
が変わらない限り、reversedMessage
が呼び出されてもfunction()
以下の処理は実行されず、前に算出したプロパティの値がそのまま出力される。
message
の値が変われば再び処理が走るが、そうでなければ何回呼び出されても計算が発生しないので、不要に処理が遅くなることがない。
じゃあmethodsっていつ使うの?
computed: { now: function () { return Date.now() } }
Date.now()
は二度と更新されない。
→ いつアクセスしても同じ日時
methodsはメソッドなので、入力値が変わらなくても、呼び出されるたびに毎回処理が走る。
算出プロパティは、それが依存するものが更新されたときにだけ再評価されます。
算出プロパティ付近のコード読んでみる
どうやって実装してるんだろう?
予想を立ててみた
- dataの値が更新されたら再評価される
- なんか
Observer
っぽい気がする。 - Vueの本に
メソッドを呼び出しているわけではないのに何かの処理をしている。これがVue.jsの心臓ともいえるリアクティブシステムです。
みたいなこと書いてた気がする
- なんか
Intersection Observer API - Web API | MDN
やってみたこと
vueのコード読んでみる。
↓
observerディレクトリがある...!
vue/src/core/observer at dev · vuejs/vue · GitHub
↓
index.js見てみる
vue/index.js at dev · vuejs/vue · GitHub
↓
defineReactive関数
見つけた。
↓
Vueの公式に Object.definePropertyを使用して getter/setter に変換します
って書いてた気がする
↓
Object.defineProperty
getter/setter
ある!
↓
Object.defineProperty
?
あるオブジェクトのプロパティを明示的に追加または変更することができます。
Object.defineProperty() - JavaScript | MDN
↓
defineReactive関数
読んでみる
↓
const dep = new Dep()
?
const dep = new Dep() // ... Object.defineProperty(obj, key, { enumerable: true, configurable: true, get: function reactiveGetter () { const value = getter ? getter.call(obj) : val if (Dep.target) { dep.depend() if (childOb) { childOb.dep.depend() if (Array.isArray(value)) { dependArray(value) } } } return value }, // ...
↓
dep.js読んでみる?
vue/dep.js at dev · vuejs/vue · GitHub
↓
続きます...!