ホームページ >ウェブフロントエンド >jsチュートリアル >Vue の応答性の原理は何ですか? vueの応答性原理の分析
この記事では、Vue の応答性の原理とは何なのかを説明します。 Vue の応答性原理の分析には一定の参考価値がありますので、お役に立てれば幸いです。
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、メソッド、データ、監視があるかどうかを判断し、対応する初期化関数を呼び出します
主なジョブは、defineProperty を呼び出して、それぞれのプロパティの get をマウントすることです (このフックがトリガーされると、現在のプロパティの dep インスタンスが現在の Dep.target (現在のウォッチャーの dep である) にプッシュされます。つまり、サブスクライブする依存関係、Dep.target これについては後述します。また、dep インスタンスは、現在のウォッチャー (オブザーバー) をその subs 配列にプッシュし、メソッドを設定します (依存するサブスクライブ内のすべてのオブザーバー ウォッチャーに呼び出しを通知します)。更新方法)。
その機能は、計算されたオブジェクト内のすべてのプロパティを走査し、そのプロパティに新しい計算されたウォッチャーを与えることです (計算されたプロパティを使用する必要があるウォッチャーをサブスクライブするために、計算されたプロパティに 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 の機能は、ウォッチ内のプロパティを走査し、ウォッチによって監視される各プロパティに対して定義された $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 に割り当てます。
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の応答性原理の分析の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。