フロントエンドエンジニアをやっています。
頑張るから読んでほしい。

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.js

やってみたこと

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 に変換します って書いてた気がする

リアクティブの探求 — Vue.js

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







続きます...!