今回は、Vue+Observer の使用方法を段階的に説明します。Vue+Observer を使用する際の注意事項 は何ですか?実際のケースを見てみましょう。
はじめに:
この記事は、Vue の公式ドキュメント (https://cn.vuejs.org/v2/guide/reactivity.html) のリアクティブ原則と実装プロセスを深く理解するものです。ソースコードの復元を通じて。
レスポンシブの原則は、コレクションに依存するプロセスと、トリガーと再レンダリングのプロセスの 2 つのステップに分けることができます。依存関係収集プロセスには、Watcher、Dep、Observer という 3 つの非常に重要なクラスがあります。この記事では主にObserverについて解説します。 この記事では、前の記事で説明できなかったオブザーバー部分の内容について説明します。まず、公式 Web サイトのこの図を見てみましょう:varvm = newVue({ el: '#demo', data: { firstName: 'Hello', fullName: '' }, watch: { firstName(val) { this.fullName = val + 'TalkingData'; }, } })
// src/core/instance/index.js functionVue(options) { if(process.env.NODE_ENV !== 'production'&& !(thisinstanceofVue) ) { warn('Vue is a constructor and should be called with the `new` keyword') } this._init(options) } // src/core/instance/init.js Vue.prototype._init = function(options?: Object) { constvm: Component = this // ... initState(vm) // ... } // src/core/instance/state.js exportfunctioninitState(vm: Component) { // ... constopts = vm.$options if(opts.data) { initData(vm) } // ... } functioninitData(vm: Component) { letdata = vm.$options.data data = vm._data = typeofdata === 'function' ? getData(data, vm) : data || {} // ... // observe data observe(data, true/* asRootData */) }
// src/core/observer/index.js functionobserve(value: any, asRootData: ?boolean): Observer| void{ // 如果不是对象,直接返回 if(!isObject(value) || value instanceofVNode) { return } letob: Observer | void if(hasOwn(value, 'ob') && value.ob instanceofObserver) { // 如果有实例则返回实例 ob = value.ob } elseif( // 确保value是单纯的对象,而不是函数或者是Regexp等情况 observerState.shouldConvert && !isServerRendering() && (Array.isArray(value) || isPlainObject(value)) && Object.isExtensible(value) && !value._isVue ) { // 实例化一个 Observer ob = newObserver(value) } if(asRootData && ob) { ob.vmCount++ } returnob }
exportclassObserver{ value: any; dep: Dep; vmCount: number; // number of vms that has this object as root $data constructor(value: any) { this.value = value this.dep = newDep() this.vmCount = 0 def(value, 'ob', this) if(Array.isArray(value)) { // ... this.observeArray(value) } else{ this.walk(value) } } walk (obj: Object) { constkeys = Object.keys(obj) for(leti = 0; i < keys.length; i++) { defineReactive(obj, keys[i], obj[keys[i]]) } } observeArray (items: Array) { for(leti = 0, l = items.length; i < l; i++) { observe(items[i]) } } }
オブジェクトの各属性を走査し、その属性に対して defineReactive メソッドを呼び出します。ここでのdefineReactiveメソッドが核心です。依存関係の収集は、Object.defineProperty メソッドを使用して、監視する必要がある各プロパティに get/set を追加することで完了します。依存関係が収集された後、各プロパティにはすべての Watcher オブジェクトを保存するための Dep が含まれます。記事の冒頭の例によると、firstName と fullName に get/set がそれぞれ追加され、それぞれに監視するすべての Watcher オブジェクトを保存する Dep インスタンスがあります。以下は、defineReactive のソース コードです:
ソース コード内の中国語のコメントによれば、defineReactive の実行中にどのような作業が行われるかを理解できるはずです。実際、プロセス全体は再帰的であり、各プロパティにゲッター/セッターを追加します。 getter/setterの場合も属性 Observerパターンごとに再帰(サブオブジェクトの判定)を完了する必要があります。 getter の場合、依存関係の収集、つまりソース コード内の dep.depend() を完了するために使用されます。セッターの場合、データの一部がその set メソッドをトリガーすると、更新メッセージが発行され、このデータのすべてのオブザーバーにデータが変更されようとしていることが通知されます。それがソースコードのdep.notify()です。この記事の事例を読んだ後は、この方法を習得したと思います。さらに興味深い情報については、php 中国語 Web サイトの他の関連記事に注目してください。
推奨読書:
vue+axiosフォームで画像をアップロードする手順の詳細な説明 axios 画像フォームを送信するための投稿リクエストを送信する手順の詳細な説明以上がVue+Observer の使用手順の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。