Vee理解の白話getter/setter
9026 ワード
原文のより良い読書体験
通常のJavaScriptオブジェクトをVueインスタンスの
以上は深い応答式の原理から抜粋した.
では、これらの属性をすべてgetter/setterに変換するのは具体的にどのようなプロセスですか?本文は深く具体的ではなく、簡単にその過程を大体理解し、全体的に把握し、その主な構想を理解することを目的としている.
仮定コードは次のとおりです.
Dataオプションは、オブジェクトまたはメソッドを受信できます.ここでは、オブジェクトを例に挙げます(実際には最後にオブジェクトに変換されます).
まず、このオブジェクトのすべてのキー値ペアが
しかし、通常は
通常
簡単な理解はvmにアクセスすることです.data.msgはvm.へのアクセスですdata.msg.開発環境でvmに直接data = xxx
そこで,
次にgetter/setter
demoを少し追加します.
msg 2はmsgに依存し、msgが変化するとmsg 2の値が自動的に更新される必要があり、msgの変化は
直感的には、すべてのcomputedオブジェクトのキー値ペアを遍歴し、分析することは理論的に可能であるように思われますが、ASTを解析する必要があるのか、あるいは正則的にマッチングして、
実際、Vueが初期化されると、
Vue応答式のコアは,getterの場合は依存を収集し,setterの場合は依存更新をトリガーする.
また、上記のcomputed msg 2を例にとると、msg 2の値を初めて取る場合(値を取る行為でなければならないことに注意し、templateでもプログラムでもよい)、必ず値
msgはどんなものに頼ることができますか?今のところ3つあるようだtemplateテンプレート computed watch
私たちは
この式は上記の3つのケースに対応しており、msgが変更された場合、これらの式は再評価する必要があるため、これらの依存項目は保存されるため、ソースコードにはこのWatcherクラスが定められている.
A watcher parses an expression, collects dependencies, and fires callback when the expression value changes. This is used for both the $watch() api and directives.
watcher.deps配列はこのwatcherの依存項を表し、値はDepインスタンスであり、Watcherインスタンスの式に関連するdataデータとして理解できる.なお、deps配列は空である可能性があり、templateではdataに依存せず、computedではこのcomputedデータはまだ取得されていません(例えば私はmsg 2を定義したが、プログラムには役に立たない.このときdepsは空である.これは私がmsgを変更した場合、msg 2に通知する必要はないことを示している.msg 2はまったく使われていないからだ.しかし、コンソールにvm.msg 2を入力し、msgのgetterをトリガーし、依存収集を行った.このときdepsは空ではない.これは私がmsg 2を使用したことを示している.次回はmsg更新時にはmsg 2に変更を通知する必要があります)
watchでは、depsが空ではない場合を試してみましたが、ソースコードの確認をさらに確認する必要があります.
deps配列要素はDepインスタンスであり、このインスタンスにはsubs属性があり、Watcherインスタンス配列であり、このDepに依存する項目を表す
WatcherとDepは理解しにくいので、一時的には理解できますが、Depとdataはフックされ、各Depインスタンスはdataのキー値ペアに対応し、WatcherインスタンスはDepに依存し、3つの状況が依存します.つまり、以上の3つです(データが新しい場合、この3つだけが同時に更新されるか、または同時に応答する必要があるか考えてみてください)
まとめ:私たちは
最後に見たら、私の公衆番号「私たちは勝手に覚えています」に注目してください.
転載先:https://juejin.im/post/5cb51871f265da0368145069
通常のJavaScriptオブジェクトをVueインスタンスの
data
オプションに渡すと、Vueはこのオブジェクトのすべてのプロパティを遍歴し、Objectを使用します.definePropertyは、これらのプロパティをすべてgetter/setterに変換します.Object.definePropertyはES 5のshimできない特性です.つまり、VueはIE 8以降のブラウザをサポートしていない理由です.以上は深い応答式の原理から抜粋した.
では、これらの属性をすべてgetter/setterに変換するのは具体的にどのようなプロセスですか?本文は深く具体的ではなく、簡単にその過程を大体理解し、全体的に把握し、その主な構想を理解することを目的としている.
仮定コードは次のとおりです.
const vm = new Vue({
el: '#app',
data: {
msg: 'hello world'
}
})
Dataオプションは、オブジェクトまたはメソッドを受信できます.ここでは、オブジェクトを例に挙げます(実際には最後にオブジェクトに変換されます).
まず、このオブジェクトのすべてのキー値ペアが
vm._data
にマウントされます(また、vm._data
オブジェクトには__ob__
keyがあり、一時的に無視できます).これにより、vm._data.msg
でデータにアクセスできます.しかし、通常は
vm.msg
でデータにアクセスしていますが、どうすればいいのでしょうか.実はエージェントをして、dataキー値ペアのvm[key]へのアクセスをvm.にエージェントしました.data[key]上proxy(vm, `_data`, key)
export function proxy (target: Object, sourceKey: string, key: string) {
sharedPropertyDefinition.get = function proxyGetter () {
return this[sourceKey][key]
}
sharedPropertyDefinition.set = function proxySetter (val) {
this[sourceKey][key] = val
}
Object.defineProperty(target, key, sharedPropertyDefinition)
}
通常
vm._data
(下線変数)は内部プログラムとして使用され、外部に露出するAPIはvm.$data、実はこの2つも1つのもので、エージェントをして、コードは大体このようにします:const dataDef = {}
dataDef.get = function () { return this._data }
Object.defineProperty(Vue.prototype, '$data', dataDef)
if (process.env.NODE_ENV !== 'production') {
dataDef.set = function () {
warn(
'Avoid replacing instance root $data. ' +
'Use nested data properties instead.',
this
)
}
}
簡単な理解はvmにアクセスすることです.data.msgはvm.へのアクセスですdata.msg.開発環境でvmに直接data = xxx
,
vm.$data.msg=xxx`のような賦値で、後者は大丈夫です)そこで,
vm.msg
,vm._data.msg
,vm.$data.msg
およびvm._data.msg
の3つの方法でデータを取得/変更できる理由を理解し,最も原始的なデータはvm.$data.msg
であり,他の2つがエージェントである.dataのデータ、vm.msg
はVueが外部に提供するAPIであり、一般的にはthis.$data
を直接使用する開発が多く、便利であり、data全体を取得するには、this.data
ではなくvm._data.msg
を使用する必要がある.次にgetter/setter
demoを少し追加します.
const vm = new Vue({
el: '#app',
data: {
msg: 'hello world'
},
computed: {
msg2() {
return this.msg + '123'
}
}
})
msg 2はmsgに依存し、msgが変化するとmsg 2の値が自動的に更新される必要があり、msgの変化は
this.msg
のsetterで監視することができるが、msg 2がmsgに依存していることをどのように知っているのだろうか.直感的には、すべてのcomputedオブジェクトのキー値ペアを遍歴し、分析することは理論的に可能であるように思われますが、ASTを解析する必要があるのか、あるいは正則的にマッチングして、
this.$data.msg
が使われているかどうかを見てみましょう.これは面倒くさいでしょう.そして、プログラムにmsg 2が使われていなければ、それは余計なことではありませんか.実際、Vueが初期化されると、
this._data.msg
のキー値ペアごとにgetter/setterが設定され、コードは次のようになります.// obj vm._data
const keys = Object.keys(obj)
for (let i = 0; i < keys.length; i++) {
defineReactive(obj, keys[i])
}
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
get: function reactiveGetter () {
const value = getter ? getter.call(obj) : val
if (Dep.target) {
dep.depend()
if (childOb) {
childOb.dep.depend()
if (Array.isArray(value)) {
dependArray(value)
}
}
}
return value
},
set: function reactiveSetter (newVal) {
const value = getter ? getter.call(obj) : val
/* eslint-disable no-self-compare */
if (newVal === value || (newVal !== newVal && value !== value)) {
return
}
/* eslint-enable no-self-compare */
if (process.env.NODE_ENV !== 'production' && customSetter) {
customSetter()
}
// #7981: for accessor properties without setter
if (getter && !setter) return
if (setter) {
setter.call(obj, newVal)
} else {
val = newVal
}
childOb = !shallow && observe(newVal)
dep.notify()
}
})
Vue応答式のコアは,getterの場合は依存を収集し,setterの場合は依存更新をトリガーする.
また、上記のcomputed msg 2を例にとると、msg 2の値を初めて取る場合(値を取る行為でなければならないことに注意し、templateでもプログラムでもよい)、必ず値
data
を取る必要があり、これはmsgのgetterをトリガーし、このときmsg 2がmsgに依存していることを確認することができる.msgはどんなものに頼ることができますか?今のところ3つあるようだ
私たちは
vm._data
を印刷することができて、Watcherインスタンスの配列で、直接インスタンスのexpression値を見て、実はこの式をトリガする時、msgのgetterをトリガしますこの式は上記の3つのケースに対応しており、msgが変更された場合、これらの式は再評価する必要があるため、これらの依存項目は保存されるため、ソースコードにはこのWatcherクラスが定められている.
A watcher parses an expression, collects dependencies, and fires callback when the expression value changes. This is used for both the $watch() api and directives.
watcher.deps配列はこのwatcherの依存項を表し、値はDepインスタンスであり、Watcherインスタンスの式に関連するdataデータとして理解できる.なお、deps配列は空である可能性があり、templateではdataに依存せず、computedではこのcomputedデータはまだ取得されていません(例えば私はmsg 2を定義したが、プログラムには役に立たない.このときdepsは空である.これは私がmsgを変更した場合、msg 2に通知する必要はないことを示している.msg 2はまったく使われていないからだ.しかし、コンソールにvm.msg 2を入力し、msgのgetterをトリガーし、依存収集を行った.このときdepsは空ではない.これは私がmsg 2を使用したことを示している.次回はmsg更新時にはmsg 2に変更を通知する必要があります)
watchでは、depsが空ではない場合を試してみましたが、ソースコードの確認をさらに確認する必要があります.
deps配列要素はDepインスタンスであり、このインスタンスにはsubs属性があり、Watcherインスタンス配列であり、このDepに依存する項目を表す
WatcherとDepは理解しにくいので、一時的には理解できますが、Depとdataはフックされ、各Depインスタンスはdataのキー値ペアに対応し、WatcherインスタンスはDepに依存し、3つの状況が依存します.つまり、以上の3つです(データが新しい場合、この3つだけが同時に更新されるか、または同時に応答する必要があるか考えてみてください)
まとめ:私たちは
this.msg
のすべてのキー値に対してgetter/setterを設定し、getterの場合は依存を収集します(依存項目は上記の3つで、どんな場合でも依存を収集するわけではありません.例えばフックにmsgを印刷すると、依存していないので、ソースコードには複雑な判断があります).setterの場合は収集の依存をトリガーします.データを更新し、これらを理解すれば、Vueの応答式の原理を初歩的に理解することができる.最後に見たら、私の公衆番号「私たちは勝手に覚えています」に注目してください.
転載先:https://juejin.im/post/5cb51871f265da0368145069