分析ソースコードシリーズ-Vue.set /vm.$set
詳細
記事のディレクトリ
機能と概念の説明
レスポンシブオブジェクトにプロパティを追加し、この新しいプロパティもレスポンシブであり、ビューの更新をトリガーすることを確認します。Vueは通常の新しいプロパティ(this.myObject.newProperty = 'hi'など)を検出できないため、リアクティブオブジェクトに新しいプロパティを追加するために使用する必要があります。
制限事項
ルートレベルのレスポンシブ属性を動的に追加することは許可されていません。といった:
// 错误写法
this.$set(this, 'newkey', 1111)
// 正确写法
this.$set(this.obj, 'newkey', 111)
// 取值: this.obj.newkey => 111
概要
Vue.set
そして、vm.$set
方法は実際には同じですが、言い回しは同じではありません- その効果は、ページに属性を動的に追加することであり、動的に追加された属性も応答属性です。
レスポンシブ属性を追加するためにsetを使用する理由
VUE応答性の原則を見て:原則を結合双方向のデータはVUE
実際に見ることができますが、応答に依存しているObject.defineProperty
とObject.defineProperty
複数のプロパティがある場合にだけ、オブジェクトの属性のいずれかに聞く必要があります
理解するためにデモを見てください:
var data = {
}
Object.defineProperty(data, 'data1', {
get: function() {
console.log('get data1')
return this.value
},
set: function(newVal) {
console.log('set data1')
this.value = newVal
}
})
data.data1 = 111 // 将会打印 set data1
console.log(data.data1) // 先打印 get data1 然后才是 111
data.data2 = 222 // 无打印,无报错
console.log(data.data2) // 直接打印222。表示没有进过 `Object.defineProperty`
ソースコードを見始める
これがデバッグ用のデモです
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
var app = new Vue({
el: '#app',
data: {
addData: {
}
}
})
debugger
app.$set(app.addData, 'newkey', 1111)
</script>
$set
当時のメソッドを最初に入力し、最初にデフォルト値のセクションに来ました。今回はnull値を返します。戻った後、再入力$set
はデバッグする必要がある部分です。
デバッグモードで、setメソッドを入力します
2行目1081は、ターゲットノードのデータ型を検出するための方法、つまり$set
最初のパラメータの検出です。
- 1085-1089は配列のタイプを決定します。結局のところ、特殊なタイプ
Object.defindPropety
は配列の変更を検出できないため、配列の変更は手動で更新されます。 - 1090-1093は、属性が以前にすでに存在しているかどうかを判断するためのものであり、存在する場合は監視を繰り返す必要はありません。
- 1095--1100は、ルートノードを
this.data
データに直接追加できないことを確認するためのものです ob
略して1094行変数が観測される(オブザーバー)ことに注意してください。また、変数が監視されているかどうかを判断するためにも使用されます- 監視されており、繰り返し監視する必要がない値は、対応する値に直接返されます
val
。また$set
、現在の戻り値を返します - オブジェクトが新しい場合は、1106行
defineReactive$$1
メソッドに進みます
リスナーdefineReactive$$1
メソッドを追加する
- 1021
new Dep
ビューの初期化deplookの分析dep分析が必要です。これには、次のプロセスの多くが含まれます。csdnはハッシュナビゲーションをサポートしていないため、手動で下にスライドして確認する必要があります〜 - 1023-1026オブジェクトが読み取り可能および書き込み可能かどうかを判別します
- 1019--1033ターゲットオブジェクト
get
とset
メソッドを取得します。 - 1035前のコードに浅い変数がありますが、この変数は存在
!shallow
しません。これは本当です。したがって、観察分析csdnを表示するobserve
メソッドの実装は、ハッシュナビゲーションをサポートしていません。表示するには、手動で下にスライドする必要があります。 - 上記の
observe
分析を読んだ後、私たちobserve
は彼の息子、サイクリングの特性がリスニングを追加することを知っています。 - 1039行目は、属性値を取得するイベントにバインドされています。対応する値を取得するとき、私
Dep.target
はそれをグローバルオブザーバーとして見ましたwatch
。したがって、継承されたメソッドからdep.target
の現在のdepend
メソッドのターゲットが呼び出された場合Dep
。これは、イベントを監視するためのコールバックを登録することと同じです(これは推定さwatch
れcomputed
、前兆が埋もれています) - 1052スタートライン
set
方式。またgetter
、内部の現在の値を取得するために独自に開始します - 1069行目、オブジェクトを新たにコピーする場合、ループ内でこれらのオブジェクトのデータ保持を再度追加する必要があります。既に保持されている場合は、スキップできます。これは上記のコードです。
- 最後の1070行は、setの後に呼び出され
dep.notify()
ます。対応するオブジェクトの更新をトリガーする必要がある時間を格納します(サブスクリプションオブザーバーモード)。値が更新されたので、関連するサブスクリプション関数に対してトリガーされます(この時点でウォッチもトリガーされ、ビューもこの時点で更新されます)。そして、フロントの前に設定値を取得する必要があるので、watch
内部のメソッドnewVal
とoldVal
はこの時点で記録されています - 最後に、現在の値が返され、
$set
メソッドの実行が終了します。
dep分析
depコードはそれほど長くありません。depはサブスクリプションセンターに相当します
- 717行目では、各部門に対応するIDがあり、自己増加していることがわかります。
- 718行目はイベントセンターと見なすことができ、すべての監視はここに保存されます
- depプロトタイプにはいくつかのメソッドがあることがわかり
addSub
removeSub
depend
notify
ます。これらはすべて、対応するモニターの操作、追加/削除、対応する依存関係の検索、およびこれらのメソッドへの通知に使用されます。 - 725行に
Dep.target
は非常に詳細なメモがあり、グローバルにユニークなビューア
コアはいくつかのaddSub
removeSub
depend
notify
方法を覚えていることです。次に、今すぐコードを確認し続けます
分析を観察する
特に思いやりのあるメモ
以下のためのオブザーバのインスタンスを作成しようとする値、
オブザーバインスタンスの値を作成しようと
成功し、観察した場合に戻り、新たな観測者を
首尾よく観察している場合、新しい視聴者が返され
たり、既存の観測値がすでにあればいずれかを持っています。
あるいは、既存のオブザーバー(値にすでに1つ含まれている場合)
-
それはそうです
value.__ob__
、このプロパティは、観察されているだろう、がある場合、これは私たちである$set
との判断の最初のステップ__ob__
-
次に、配列を区別します。配列にはオブザーバーがありません
-
主に1003の線を表示する
new Observe
には、現在のオブジェクトではなく、首都に注意する新しいオブザーバーを作成します -
new Observe
下の図2では、個別に説明しません。 -
926行。
__ob__
プロパティを追加するには、間違いなく、__ob__
列挙できないタイプに設定してください。詳細については、926に入るコードを見ることができます -
927-933はすべて配列操作用です
-
行935、現在のオブジェクトのwalkメソッド。コードを直接貼り付けると、それがループであり、オブジェクトを1回トラバースし、オブジェクトごとに呼び出すことがわかります
defineReactive$$1
。ご覧のとおり、このメソッドは、値がオブジェクトタイプの場合にのみ呼び出されます。 -
と呼ばれて
defineReactive$$1
いるので。次に、ここで再帰が形成されます。再帰の先頭は、属性がオブジェクトでなくなったときに呼び出しを停止することdefineReactive$$1
です。 -
これを見た後、次のステップに戻って、defineReactive $$の1035行をリッスンするメソッドを追加する必要があります
/**
* Walk through all properties and convert them into
* getter/setters. This method should only be called when
* value type is Object.
*/
Observer.prototype.walk = function walk(obj) {
var keys = Object.keys(obj)
for (var i = 0; i < keys.length; i++) {
defineReactive$$1(obj, keys[i])
}
}
総括する
-
vueレスポンシブの原則は、これら2つのメソッドのメソッドとメソッドにそれぞれ依存し
Object.defindPropety
て、対応するイベントをトリガーしますget
set
-
JSと
Object.defindPropety
動的に追加できない制限のため、プロパティを監視する必要があるため、Vue.set()
このメソッドを使用する必要があります -
Vue.set()
メソッドの内部は循環処理プロセスです。現在の新しいモニターがオブジェクトの場合、最後のサブ属性が数组/非对象类型
パラメーターになるまで、それ自体を呼び出して再帰を形成し続け、再帰が終了してから、あなた自身、モニターでそれは他の関連するメソッドをトリガーします(Depでサブスクライブされたイベントがトリガーされます)。一般的な双方向データバインディングを形成する -
以来
Object.defindPropety
変更は唯一の配列の変更内の特定のインデックスの値がそのように使用しなければならない、を聞いていないので、オブジェクト、監視することができVue.set
、手動で更新をトリガにし、この時間は、Vue.set
唯一の更新された値を行い、新規増加の監視を繰り返すことはしません
最初の元の記事:ソースコードシリーズの分析-Vue.set /vm.$set
詳細な説明これは新しいブログアドレスです。興味があればご覧ください。