ホームページ  >  記事  >  ウェブフロントエンド  >  Vue の応答性の原理は何ですか? vueの応答性原理の分析

Vue の応答性の原理は何ですか? vueの応答性原理の分析

不言
不言オリジナル
2018-09-10 15:33:512601ブラウズ

この記事では、Vue の応答性の原理とは何なのかを説明します。 Vue の応答性原理の分析には一定の参考価値がありますので、お役に立てれば幸いです。

initState

new Vue() => _init() => initState:

function initState (vm: Component) {
  vm._watchers = []
  const opts = vm.$options
  if (opts.props) initProps(vm, opts.props)
  if (opts.methods) initMethods(vm, opts.methods)
  if (opts.data) {
    initData(vm)
  } else {
    observe(vm._data = {}, true /* asRootData */)
  }
  if (opts.computed) initComputed(vm, opts.computed)
  if (opts.watch && opts.watch !== nativeWatch) {
    initWatch(vm, opts.watch)
  }
}

vue インスタンスに props、メソッド、データ、監視があるかどうかを判断し、対応する初期化関数を呼び出します

initData

主なジョブは、defineProperty を呼び出して、それぞれのプロパティの get をマウントすることです (このフックがトリガーされると、現在のプロパティの dep インスタンスが現在の Dep.target (現在のウォッチャーの dep である) にプッシュされます。つまり、サブスクライブする依存関係、Dep.target これについては後述します。また、dep インスタンスは、現在のウォッチャー (オブザーバー) をその subs 配列にプッシュし、メソッドを設定します (依存するサブスクライブ内のすべてのオブザーバー ウォッチャーに呼び出しを通知します)。更新方法)。

initComputed

その機能は、計算されたオブジェクト内のすべてのプロパティを走査し、そのプロパティに新しい計算されたウォッチャーを与えることです (計算されたプロパティを使用する必要があるウォッチャーをサブスクライブするために、計算されたプロパティに dep 依存関係が定義されます) 。 Computed は、defineProperty を呼び出すことで get (get メソッド) および set メソッドでもマウントされます (set メソッドは、渡されるかどうかを決定し、渡されない場合は、noop の空の関数に設定されます)
計算されたプロパティのメソッドは、次の関数の戻り値関数です

function createComputedGetter (key) {
  return function computedGetter () {
    const watcher = this._computedWatchers && this._computedWatchers[key]
    if (watcher) {
      watcher.depend()
      return watcher.evaluate()
    }
  }
}

watcher.depend() に注意してください。このメソッドにより、属性を使用するウォッチャー オブザーバーがウォッチャー内の依存関係にサブスクライブできるようになり、計算された属性が得られます。ウォッチャーは、それをサブスクライブするウォッチャーをサブスクライブにプッシュします (計算された属性の値が変更されたとき、それをサブスクライブするウォッチャー オブザーバーに通知します)
watcher.evaluate()。これは、ウォッチャーの get メソッドを呼び出すことによって行われます (これは、ウォッチャーの get メソッドは、pushTarget を呼び出して前の Dep.target インスタンスをスタックに置き、計算されるように Dep.target を設定することに注意してください。 ウォッチャー、計算されたプロパティが依存する応答プロパティは、 ウォッチャーはそのサブルーチンにプッシュされるため、依存する応答プロパティが変更されると、それをサブスクライブする計算されたウォッチャーに通知されます。 次に、計算された属性をサブスクライブしているウォッチャーに update メソッドを呼び出すように通知し、get メソッドで計算された属性キーにバインドされたハンドラー関数を呼び出して値を計算します。

initWatch

このウォッチャーはユーザーウォッチャーです(コンポーネントで開発者によってカスタマイズされます)。
initWatch の機能は、ウォッチ内のプロパティを走査し、ウォッチによって監視される各プロパティに対して定義された $watch を呼び出すことです。

Vue.prototype.$watch = function (
    expOrFn: string | Function,
    cb: any,
    options?: Object
  ): Function {
    const vm: Component = this
    if (isPlainObject(cb)) {
      return createWatcher(vm, expOrFn, cb, options)
    }
    options = options || {}
    options.user = true // 代表该watcher是用户自定义watcher
    const watcher = new Watcher(vm, expOrFn, cb, options)
    if (options.immediate) {
      cb.call(vm, watcher.value)
    }
    return function unwatchFn () {
      watcher.teardown()
    }
  }

コード内で新しい Watcher を呼び出すと、ウォッチャーの get メソッドが実行され、pushTarget が呼び出されます。レンダー ウォッチャーと同様に、現在のユーザー ウォッチャーを Dep.target に割り当てます。get() 内のステートメント value = this.getter.call(vm, vm) は、カスタム ウォッチャーによって監視される応答属性の get メソッドをトリガーします。現在のユーザーを設定する ウォッチャーは、この属性が依存するサブオブジェクトにプッシュするため、ユーザーが ウォッチャーによって監視されているプロパティ セットがトリガーされると、依存関係にサブスクライブしているウォッチャーに更新をトリガーするように通知されます。つまり、ウォッチにバインドされたキーに対応するハンドラーがトリガーされます。次に、popTarget を呼び出してスタックをポップし、それを Dep.target に割り当てます。

$mount

initStateの初期化作業はここで大まかに完了し、その後、$mountが実行されてレンダリング作業が開始されます
$mountの主な作業: 新しいレンダリングウォッチャーを作成し、コールバックとしてupdateCompentを渡し、

updateComponent = () => {
      vm._update(vm._render(), hydrating)
    }
new Watcher(vm, updateComponent, noop, {
    before () {
      if (vm._isMounted) {
        callHook(vm, 'beforeUpdate')
      }
    }
  }, true /* isRenderWatcher */)

を実行します3 つのウォッチャー 新しいウォッチャーが追加されると、計算されたウォッチャーのみが最初から get() メソッドを実行しません。 $mount の新しいレンダー ウォッチャーは get() メソッドと PushTarget を呼び出して、現在のレンダー ウォッチャーを Dep.target に割り当てます。次にハイライトとなるのは、updateComponent を呼び出して vm._update(vm._render(), ハイドレーティング) を実行することです。これにより、レンダー関数が HTML で使用される応答属性の get フックをトリガーします。 get フックにより、レスポンシブ プロパティの依存インスタンス dep が現在のレンダリングを変換します。 ウォッチャーはその subs 配列にプッシュされるため、依存する応答プロパティが変更されると、サブスクライブをトラバースして、サブスクライブしているウォッチャーに update() を呼び出すように通知します。

おそらく、watcher と dep を調整する方法について混乱しているかもしれません。例を挙げてみましょう

<div id="app">
      <div>{{a}}</div>
      <div>{{b}}</div>
    </div>
new Vue({
  el: "#app",
  data() {
    return {
      a:1,
    }
  },
  computed:{
    b() {
      return a+1
    }
  },
})

レンダリングから直接開始し、dep と watcher についてのみ説明します
$mount: new レンダリング ウォッチャー (レンダリングウォッチャーが Dep.target に割り当てられている場合、ウォッチャーの get メソッドは vm._update(vm._render(), ハイドレーティング) をトリガーします。上記の例では、最初に html で使用される応答属性が取得されます。を使用すると、 a の get フックがトリガーされ、 dep.depend() が現在のレンダリング ウォッチャーを a 属性の dep の subs 配列にプッシュします。

実行を続行し、 b (b は計算された属性の値) にアクセスします。これにより、計算された属性の get メソッドがトリガーされます。計算されたプロパティの get メソッドは、createComputedGetter 関数を呼び出した後に返される computedGetter 関数であり、watcher.depend() は computedGetter 関数内で実行されます。 Watcher の depend メソッドは計算専用に予約されています。 ウォッチャーが使用します。

上で述べたように、計算されたウォッチャーに加えて、他の 2 つのウォッチャーは新しいものにあります。 その後、get メソッドが実行され、計算されます。 new が完了した後、watcher は新しい dep を作成しますか?

計算されたウォッチャーについて先ほど述べたメソッド watcher.depend() に戻ります。その機能は this.dep.depend() を実行することです (ここでは計算されたウォッチャーによって定義された dep が使用されます)。 this.dep.depend() により、現在のレンダリング ウォッチャーは計算されたプロパティの依存関係にサブスクライブされます。また、計算されたプロパティの値が変更されると、計算されたプロパティはレンダリング ウォッチャーを独自のサブクラスにプッシュします。 、計算された属性値が変更された場合にページを更新できるように、subs のウォッチャーに update() を呼び出すように通知します。

前述の b の計算された属性をトリガーした get フックに戻り、get フックは最後に watcher.evaluate() を実行し、watcher.evaluate() は計算された watcher の get() メソッドを実行します。

この時点で重要な点が来ます。 Dep.target (レンダー ウォッチャー) は (継続使用のために後で取り出せるように保存された後) targetStack スタックにプッシュされ、その後、この計算された属性の計算されたウォッチャーがプッシュされます。 Dep.targetに配属されます。 get メソッドでは、value = this.getter.call(vm, vm) により、計算された属性にバインドされたハンドラーが実行されます。

上記の例のように、+1を返します。 a が使用される場合、a の get フックがトリガーされ、get フックは dep.depend() を呼び出します。dep.depend() により、計算されたウォッチャーは dep を deps 配列に格納し、a の dep は現在の dep を格納します。 Dep.target (計算されたウォッチャー) はその subs 配列に格納されます。この例では、 a のサブは [レンダー ウォッチャー、計算されたウォッチャー] となるため、 a の値の変更は a のサブのウォッチャーを横断します。そして、 update() メソッドを呼び出します。 HTML で使用される a は更新されます。計算された属性ウォッチャーが update() メソッドを呼び出すと、それ自体の subs ([render) ウォッチャー]) レンダリング中 ウォッチャーが update メソッドを呼び出すと、HTML で使用される計算属性 b によって dom が更新されます (ここで注意してください。これは大まかに話しているだけですが、計算属性が依存する属性が変更された後に必ずしも更新がトリガーされるわけではありません。計算が完了した後に比較します) 値が変化するかどうか)。

計算済み ウォッチャーの get() メソッドは最後に PopTarget() を呼び出し、以前に保存されたレンダー ウォッチャーをスタックから取り出して Dep.target に割り当てます。このとき、この例の targetStack は空の配列になります。

Render Watcher の get メソッドは実行終了時にスタックからポップアウトされ、この時点では Dep.target に割り当てられた値は空になります。

関連する推奨事項:

Vue データの応答性の原則分析

Vue の応答性の原則について (詳細なチュートリアル)


以上がVue の応答性の原理は何ですか? vueの応答性原理の分析の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。