VUEのアクティブシステム(VUE 2)
reactとは異なり、Vueは
一般的なブログ記事はVuejsはgetters/settersを用いてこれが可能であることを示していますが、このように説明するだけでは、どのような方法で現れるのでしょうか.正式な書類を見ているだけでは理解できないので、イメージを参考にして、理解した内容に基づいて書きます.
その前にVueまずjs公式文書を見てみましょう.
以下の画像は公式文書の内容を写している.
VueインスタンスでのJavaScriptオブジェクトの使用
ユーザーにはgetter/setterは表示されませんが、プロパティにアクセスまたは変更すると、Vueは依存追跡および変更通知を実行できます.変換後のデータ・オブジェクトを記録すると、ブラウザは異なるgetter/setterフォーマットを処理し、熟知したインタフェースを使用することに注意してください. vue-devtoolsのインストールを推奨します.
すべての構成部品インスタンスに適用 watcher コンポーネント依存レンダリング中に[修正](Modify)のすべてのアトリビュートが記録されるインスタンスがあります.依存setterがトリガーされると、watcherに通知され、構成部品が再レンダリングされます.
まず、VUEが反応性システムのためにgetter/setterを使用する理由を理解するためには、まず依存性(dependency)と監視プログラムの2つの概念を理解しなければならない.
このようなJavascriptコードがあります
しかし、上記のコードはグローバル変数を乱用し、カプセル化されたコードもない.上のコードをクラスに入れます.
以上の
これまでのコードは、各変数に
この状態の更新を監視する論理をカプセル化することが望ましい. このため、
図各変数は
解決策のために、
2 次に、各
また、属性が更新されるタイミングも決定される(
簡単に言えば、
そのため、Vue.jsはObject.defineProperty()を使用します.ここにはgetter/setterの概念があります.
これはVueですこれによりjsで実行されるコードが大幅に簡略化される.しかし、全体のフレームワークは同じです.(Vue.jsスポンサーのビデオだからでしょ?)
時間があればぜひBuild a Reactivity Systemという動画を見てください説明が上手で、無料です.
また、VUEのReactivity Systemについて詳しく知りたい場合は、deep-dive-into-reactivity-in-depthを参照してください.
Build a Reactivity System
反応型を深く理解する
deep-dive-into-reactivity-in-depth
setState()
のような設定状態の関数を使用せず、データ(すなわち状態)を変更することによって自動的に状態を更新する.どうしてそんなことができるの?これが気になってこの文章を書いた一般的なブログ記事はVuejsはgetters/settersを用いてこれが可能であることを示していますが、このように説明するだけでは、どのような方法で現れるのでしょうか.正式な書類を見ているだけでは理解できないので、イメージを参考にして、理解した内容に基づいて書きます.
その前にVueまずjs公式文書を見てみましょう.
変更を追跡します。
以下の画像は公式文書の内容を写している.
VueインスタンスでのJavaScriptオブジェクトの使用
data
オプションとして渡すと、Vueは Object.definePropertyの使用 getter/settersに変換します.これがVueがIE 8以下のES 5をサポートしない理由です.ユーザーにはgetter/setterは表示されませんが、プロパティにアクセスまたは変更すると、Vueは依存追跡および変更通知を実行できます.変換後のデータ・オブジェクトを記録すると、ブラウザは異なるgetter/setterフォーマットを処理し、熟知したインタフェースを使用することに注意してください. vue-devtoolsのインストールを推奨します.
すべての構成部品インスタンスに適用 watcher コンポーネント依存レンダリング中に[修正](Modify)のすべてのアトリビュートが記録されるインスタンスがあります.依存setterがトリガーされると、watcherに通知され、構成部品が再レンダリングされます.

まず、VUEが反応性システムのためにgetter/setterを使用する理由を理解するためには、まず依存性(dependency)と監視プログラムの2つの概念を理解しなければならない.
このようなJavascriptコードがあります
let price = 5
let quantity = 2
let total = price * quantity // 10
price = 20
console.log(`total is ${total}`) // 10
一番下のコンソールのtotal
は10です.price
は20になりましたが、もちろん結果は10です.このコードをVue更新状態に変換しましょう.Problem
total
またはtotal
を変更するには、price
を再実行するには、quantity
をどこかに保存します.最終的には、total
をどこかに保存することが重要です.Solution
price
またはquantity
変数を更新する場合は、保存されたtotal
を再実行する必要があります.total
関数を作成して、record()
を格納します. let price = 5
let quantity = 2
let total = 0
let target = null
target = function () {
total = price * quantity
}
let storage = [] // target function을 저장할 배열
price = 20
function record () {
storage.push(target) // record 함수는 stoarge 배열에 target 함수를 저장한다.
}
record() // total을 저장하기
target()
storage
アレイに格納されたtarget
を取り出し、replay()
関数を作成します. function replay (){
storage.forEach(run => run())
}
let price = 5
let quantity = 2
let total = 0
let target = null
let storage = []
function record () {
storage.push(target)
}
function replay () {
storage.forEach(run => run())
}
target = () => { total = price * quantity }
record()
target()
price = 20
console.log(total) // => 10
replay()
console.log(total) // => 40
完全なコードを見てみましょう.record()
によりtotal
が格納され、保存されたtotal
を取り出すためにreplay()
関数が呼び出される.では、一番下のコンソールは変化した価格を撮影します.40.しかし、上記のコードはグローバル変数を乱用し、カプセル化されたコードもない.上のコードをクラスに入れます.
上の論理をClassで置き換えましょう
以上の
record(), replay(), storage
等はいずれも状態に関する論理であるため,クラスに分類する. class Dep { // Stands for dependency
constructor () {
this.subscribers = [] // storage 배열을 대체한다. 이게 흔히들 알고 있는 의존성 배열이다.
}
depend() { // record() 함수를 대체한다.
if (target && !this.subscribers.includes(target)) {
this.subscribers.push(target)
}
}
notify() { // replay() 함수를 대체한다.
this.subscribers.forEach(sub => sub())
}
}
では、今からコンソールでprice
を撮りましょう.subscribers
配列を依存配列と呼ぶ.コンソールを確認して、出力が正常であることを確認します. const dep = new Dep()
let price = 5
let quantity = 2
let total = 0
let target = () => { total = price * quantity }
dep.depend() // 의존성 배열에 현재 target 추가
target() // total을 얻기 위해 target 호출
console.log(total) // => 10
price = 20
console.log(total) // => 10
dep.notify() // 배열 내부의 함수 실행
console.log(total) // => 40
Watcher
これまでのコードは、各変数に
Dep
クラスを提供する.もちろん、現在のコードも正常に動作しますが、監視状態の更新を継続する論理dep.depend()
とtarget()
が面倒です.この状態の更新を監視する論理をカプセル化することが望ましい. このため、
watcher
関数を作成します. // target, dep.depend()를 대신해서
target = () => { total = price * quantity }
dep.depend()
target()
// watcher를 함수(캡슐화를 위한)를 이렇게 만들어보고 싶다는 것이다.
watcher(() => {
total = price * quantity
})
では、このwatcher
関数の内部はどのように構築されるのでしょうか.watcher
関数の内部には、コンソール上での撮影時に上記の結果を得るために以下の内容が記述されている. function watcher(myFunc) {
target = myFunc // 콜백 함수 myFunc
dep.depend() // 의존성 배열에 myFunc를 추가
target() // 받아온 함수 myFunc, 즉 target을 호출
target = null // Reset target
}
price = 20
console.log(total)
dep.notify()
console.log(total)
さらに、notify()
も単独で呼ばないようにしたい.notify()
も状態に関する論理なので、カプセル化できる案はありますか?
図
Dep
クラスを有する解決策のために、
data
オブジェクト内にprice
属性およびquantity
属性が付与される.let data = { price: 5, quantity: 2 }
このように変更すると、上記のwatcher
関数も以下のように変更されます. watcher(() => {
total = data.price * data.quantity
})
この場合、新しいwatcher
関数が呼び出され、今回呼び出されたwatcher
はdata.quantity
にぶつからず、data.price
にぶつかるだけです. watcher(() => {
salePrice = data.price * 0.9
})
現在の状況を図で要約すると以下のようになる.
data.price
を監視する2つのwatcher
関数が見られる.Dep
の内部でどの属性(price, quantity
)がアクセスされ、どのwatcher
インスタンスが呼び出されるかを決定する必要がある.これを画像で以下のように表現します.
また、属性が更新されるタイミングも決定される(
price, quantity
).これを確認すれば、dep.notify()
クラスからDep
をいつ呼び出すべきかがわかります.簡単に言えば、
dep.notify()
を呼び出す必要がなくなります.
そのため、Vue.jsはObject.defineProperty()を使用します.ここにはgetter/setterの概念があります.
Object.defineProperty()
メソッドの3番目のパラメータdescriptor
の内部の属性get, set
を定義する.次のコードを見てください. let data = { price: 5, quantity: 2 }
Object.defineProperty(data, 'price', { // price 속성만
get() { // get 메서드 생성
console.log(`I was accessed`)
},
set(newVal) { // set 메서드 생성
console.log(`I was changed`)
}
})
data.price // This calls get()
data.price = 20 // This calls set(20)
このようにしてget, set
のオーバーシュートを実現した.概念がわかった以上、実際に書いたコードに適用しましょう. // 코드에 적용된 예시 (data.price만)
let data = { price: 5, quantity: 2 }
let internalValue = data.price // data.price를 저장하기 위한 변수 internalValue
Object.defineProperty(data, 'price', {
get() { // Create a get method
console.log(`Getting price: ${internalValue}`)
return internalValue
},
set(newVal) {
console.log(`Setting price to: ${newVal}` )
internalValue = newVal // 현재 value를 set 해준다.(바꿔준다)
}
})
total = data.price * data.quantity // This calls get()
data.price = 20 // This calls set()
では現在はdata.price
だけでなく、data.quantity
にも当てはまるでしょう. let data = { price: 5, quantity: 2 }
Object.keys(data).forEach(key => { // data객체의 key를 순회하기 위해
let internalValue = data[key]
Object.defineProperty(data, key, {
get() {
console.log(`Getting ${key}: ${internalValue}`)
return internalValue
},
set(newVal) {
console.log(`Setting ${key} to: ${newVal}` )
internalValue = newVal
}
})
})
total = data.price * data.quantity
data.price = 20
今さっき作成したwatcher()
関数を結合するとVueこれはjsのデータ反応性システムとある程度似ている.最終コード
let data = { price: 5, quantity: 2 }
let target = null
// 아까 봤던 Dep class이다.
class Dep {
constructor () {
this.subscribers = []
}
depend() {
if (target && !this.subscribers.includes(target)) {
this.subscribers.push(target)
}
}
notify() {
this.subscribers.forEach(sub => sub())
}
}
// Go through each of our data properties
Object.keys(data).forEach(key => {
let internalValue = data[key]
// Each property gets a dependency instance
const dep = new Dep()
Object.defineProperty(data, key, {
get() {
dep.depend() // <-- Remember the target we're running
return internalValue
},
set(newVal) {
internalValue = newVal
dep.notify() // <-- Re-run stored functions
}
})
})
// 더 이상 watcher 함수는 dep.depend()를 호출할 필요가 없게 된다.
// 위에서 get 메서드에서 호출 중이기 때문
function watcher(myFunc) {
target = myFunc
target()
target = null
}
watcher(() => {
data.total = data.price * data.quantity
})
n/a.結論
これはVueですこれによりjsで実行されるコードが大幅に簡略化される.しかし、全体のフレームワークは同じです.(Vue.jsスポンサーのビデオだからでしょ?)
時間があればぜひBuild a Reactivity Systemという動画を見てください説明が上手で、無料です.
また、VUEのReactivity Systemについて詳しく知りたい場合は、deep-dive-into-reactivity-in-depthを参照してください.
コメントリンク
Build a Reactivity System
反応型を深く理解する
deep-dive-into-reactivity-in-depth
Reference
この問題について(VUEのアクティブシステム(VUE 2)), 我々は、より多くの情報をここで見つけました https://velog.io/@ken1204/Vue의-Reactivity-System-Vue2テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol