Help us understand the problem. What is going on with this article?

Vueの算出プロパティが依存するデータを把握する仕組み

More than 1 year has passed since last update.

Vueには算出プロパティという、関数が依存するデータの変更を検知して関数を再実行してビューに反映させる機能があります。

算出プロパティを使ったコードの例

<div id="el">
<!-- 算出プロパティを使用しているところ。foobarと表示される -->
{{ computedValue }}
</div>
new Vue({
  el: "#el",
  data: function () {
    return {value: 'foo'}
  },
  computed: {
    // これが算出プロパティの定義
    function computedValue () {
      return this.value + 'bar'
    }
  }
})

算出プロパティである computedValue() が this.value に依存していて、this.value = 'hoge' のようにして値を変更するとcomputedValueは再計算され、foobarだった表示がfoohogeになります。
データを変更するとすべての算出プロパティが再計算されるのではなく、本当に依存している算出プロパティだけが再計算されるのです。
なぜこんなことが可能なのか理解できなかったのでソースを追って調べてみました。

思いつかなかっただけですごく簡単でした。(最初はコードをパースしないと分からなくない?と思いましたが)

算出プロパティが実行される時に依存関係を発見する仕組みになっていました。
算出プロパティはWatcherというクラスで表されます。
また、その他のVueで管理されるデータはObserverというクラスで表されます。
このWatcher、Observerと依存を管理するDepというクラスを読むと仕組みが理解できます。

src/core/observer/index.js (Observerはここに定義)
src/core/observer/watcher.js
src/core/observer/dep.js

算出プロパティが呼ばれるとWatcher#get()という関数が呼ばれます。
この関数が呼ばれると、自分自身を依存元を示すオブジェクトとしてマークしてから、実際の値を計算する関数を呼び出します。
値を計算するために依存先データのgetterが呼ばれるので、このときにマークしてあったオブジェクトを依存元(自分の変更を通知しなければならない対象)として追加します。
これで依存関係を正しく把握することができます。

すごーくおおざっぱに擬似的なコードを書くとこんな感じになっています。

class Dep {
  constructor () {
    this.deps = []
  }
  add (target) {
    this.deps.push(target)
  }
  notify () {
    // 変更したことを this.deps に含まれるオブジェクトに伝える
  }
}

let depTarget = null
class Watcher {
  get () {
    depTarget = this
    this.getter.call()  // ここで実際の計算を行う
    depTarget = null
  }
}

class Observer {
  constructor (getter) {
    this.dep = new Dep()
    this.getter = getter
  }
  // 計算の中でデータを参照すると呼ばれる
  get () {
    this.dep.add(depTarget)    // 依存対象を追加する
    return this.getter.call()  // 実際の値を取得
  }
  set () {
    this.dep.notify()  // 自分自身の変更を伝える
  }
}

わかってしまえば簡単なものですね。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした