Vueの深い応答式の原理

3574 ワード

変化を追跡するにはどうすればいいですか?
jsオブジェクトをVueインスタンスのdataオプションに渡し、Vueはこのオブジェクトのすべてのプロパティを巡り、
Object.defineProperty
を通じてこれらのプロパティをsetter/getterに変換します.すなわち、インスタンスの初期化中にVueの内部メソッド_proxyはdataの属性のkeyを遍歴し、
Object.defineProperty
によってこれらの属性をsetter/getterに変換し、dataの属性をvmインスタンスにエージェントする.ユーザにはgetter/setterは見えませんが、内部Vueでは依存を追跡し、属性がアクセスされ、変更されたときに変化を通知します.各コンポーネントインスタンスには、コンポーネントレンダリング中にアトリビュートを依存として記録するwatcherインスタンスオブジェクトがあります.その後、依存項目のsetterが呼び出されると、watcherに再計算を通知し、関連するコンポーネントを新しいものにする.
Vue.jsソース解析:深い応答式原理
dataにない属性は、Vueでは検出できません.Vueでは、作成したインスタンスにルートレスポンス属性を動的に追加することはできませんが、
Vue.set(object, key ,value)
メソッドでネストされたオブジェクトにレスポンス属性を追加できます.vm.$も使用できます.setインスタンスメソッドは、グローバルVueである.setメソッドの別名.
this.$set(this.object, key, value)
例:var app1 = new Vue({ el:'#example', data:{ test:{ } } }); app1.$set(app1.test, 'b', 2); console.log(app1.test); // Object, b:2
しかし、次の書き方では、app1.$set(app1.$data, 'b', 2); //undefinedは、ルート属性の動的追加が許可されないため、所望の効果は得られない.Objectも使用できる.assign()は元のオブジェクトのプロパティを拡張します.this.someObject = Object.assign({}, this.someObject, { a: 1, b: 2 })
例:app1.$set(app1.test, 'b', 2); app1.test = Object.assign({}, app1.test, {'a':1, 'c':3}); console.log(app1.test); //Object :a:1, b:2, c:3
知識の拡張:
VUEAngularはいずれも双方向データバインディングを実現し,メカニズムは異なる.
Angularの双方向バインドは汚れた検査機構を用いて実現した.実現メカニズムは以下の通りである:データの変化を引き起こす可能性のあるイベントをカプセル化し、これらのイベントがトリガーされるたびに、データを一度チェックし、データが変化していることを発見したら、相応の更新コールバックを行う.しかし、あるイベントがトリガーされたとき、どのデータをチェックする必要がありますか?このイベントが変化をもたらす可能性のある対応データは知られていないので,すべてのデータを乱暴に完全にチェックしなければならない.しかし、あるデータが変わったのは、自分だけでなく、他のデータにも影響を与える可能性があります.したがって、1回の完全検査が1つの検査サイクルと見なされる場合、私たちは少なくとも2つのサイクルを行う必要があります.2番目のサイクルは、前回のデータ変動で、他のデータ変動が発生したかどうかを確認するために使用されます.2パス目の周期にも変動がある場合は、2回目の検査のデータが完全に一致するまで3回目の検査周期を継続する必要があります.(同級生から)
VUEデータハイジャック方式の核心はObjectに依存する.defineProperty().これはvueの双方向バインドを支えていると言わざるを得ない.Object.defineProperty()はgetterとsetterを用いてオブジェクトの各属性をハイジャックすることができ,set値が設定されるとデータが変動し,そのとき観察者に通知し,コールバック更新を行う.この方式のコアコンポーネントには4つの点があります.
  • Observer:データリスナー、データをドッキングし、データオブジェクトのすべての属性をリスニングすることができ、リスニングしたデータに変動があれば、最新値を取得し、購読者
  • に通知することができる.
  • Compile:コマンド解析器、ドッキングdom、各要素ノードのコマンドのスキャンと解析、コマンドテンプレートによるデータの置換、および対応する更新関数
  • のバインド
  • Watcher:ObserverとCompileの橋渡しを接続し、各属性の変動の通知を購読して受け取ることができ、命令バインディングの対応するコールバック関数を実行し、ビューを更新することができます.
  • MVVM:エントリ関数、統合以上の3つの
  • 非同期更新キュー:
    まず、イベントループとは何かを理解しますか?JavaScriptの実行メカニズムの詳細:Event Loopという文章をはっきり書いています.
    まだ気づいていないかもしれませんが、VueはDOM更新を非同期で実行します.データの変化が観察される限り、Vueはキューを開き、同じイベントサイクルで発生したすべてのデータの変化をバッファリングします.同じwatcherが複数回トリガーされると、キューに一度だけ押し込まれます.このようなバッファリング時に重複データを除去することは,不要な計算やDOM動作を回避する上で非常に重要である.次に、次のイベントループ「tick」で、Vueはキューをリフレッシュし、実際の(重複した)作業を実行します.Vueは内部で非同期キューに対してオリジナルのPromiseを使用することを試みる.thenとMutationObserverは,実行環境がサポートされていない場合にsettimeout(fn,0)を採用する.
    例えばvmを設定するとsomeData='new value'で、このコンポーネントはすぐに再レンダリングされません.キューをリフレッシュすると、イベントループキューが空になったときにコンポーネントが次のtick更新されます.多くの場合、このプロセスに関心を持つ必要はありませんが、DOMステータスの更新後に何かをしたい場合は、少し難しいかもしれません.Vuejsは通常、開発者がDOMに直接接触しないように「データ駆動」に沿って考えることを奨励していますが、時にはそうする必要があります.データが変化する後にVueの更新DOMが完了するのを待つために、データが変化する直後にVueを使用することができる.nextTick(callback).これにより、コールバック関数はDOM更新が完了すると呼び出されます.例:{{message}} var vm =new Vue({ el:'#example', data: { message:'123' } }) vm.message ='new message'// vm.$el.textContent ==='new message'// false Vue.nextTick(function(){ vm.$el.textContent ==='new message'// true })