VUE-MVVM-part 10-Computed
8398 ワード
この文章を読む前に、前の文章を読んでいなかったら、文章の最後に引いて前の文章を調べます.
回顧する
まずしごきをします.前に実現した属性および方法のプロキシ 傍受属性 事件 現在の
後の2つは親のコンポーネントと関係があるので、先に置いておいて、
Computed
公式文書には次のような言葉があります.
属性の計算結果は、依存する応答属性が変化しない限り再計算されます.
これは属性性能の計算が使用方法に比べて良い理由でもある.
okこれを実現します.まず属性を計算する形式を決めます.
慣例はテストコードを通して、私達はどんな機能を実現したいですか?による属性計算は、 である.第1回起動時に を出力しませんでした.依存性が変化すると、再度 を呼び出した.
解決
第一のポイントはよく解決します.
了解したら、私達はそれを実現します.同じように分かりやすいように、一つの種類を書きました.
しかし、属性を計算するには本当にリアルタイムで対応する値を更新する必要がありますか?
まず、依存性の属性が変化すると計算属性の変化が起こることを知っています.言い換えれば、計算属性が変化すると、
第二に、私たちは計算属性が必ず使われることを保証できません.
第1の点に基づいて、属性を計算することは、ビューの変化をトリガする必要はないので、属性を計算することは、取得時に対応する値を更新すればよい.
Watchの汚れ検査メカニズム
上記の分析によれば、
okこれから上の疑似コードを実現します.
しかし、上記のコードは
ok
クリックして関連コードを調べます.
シリーズの記事アドレス VUE-MVVM-part 1-defineProperty VUE-MVVM-part 2-Dep VUE-MVVM-part 3-Watch VUE-MVVM-part 4-最適化Watch VUE-MVVM-part 5-Observe VUE-MVVM-part 6-Aray VUE-MVVM-part 7-Event VUE-MVVM-part 8-Eventを最適化する VUE-MVVM-part 9-Vue VUE-MVVM-part 10-Computed VUE-MVVM-part 11-Exted VUE-MVVM-part 12-props VUE-MVVM-part 13-inject&総括
回顧する
まずしごきをします.前に実現した
Vue
類は主に以下の機能があります.proxy
watcher
Vue
におけるデータ処理と比べて、まだ実装されていないものがあります.Computed
、props
、provied/inject
.後の2つは親のコンポーネントと関係があるので、先に置いておいて、
Computed
を実現します.Computed
公式文書には次のような言葉があります.
属性の計算結果は、依存する応答属性が変化しない限り再計算されます.
これは属性性能の計算が使用方法に比べて良い理由でもある.
okこれを実現します.まず属性を計算する形式を決めます.
{
get: Function,
set: Function
}
公式は私達に二種類の形式でComputed
を書きにきました.ソースコードを見て、最終的にはこのような形に処理されていることが分かりました.だから、私達はまずこの形式を直接使って、後で統一化処理をします.慣例はテストコードを通して、私達はどんな機能を実現したいですか?
let test = new Vue({
data() {
return {
firstName: 'aco',
lastName: 'Yang'
}
},
computed: {
computedValue: {
get() {
console.log(' ')
return this.firstName + ' ' + this.lastName
}
},
computedSet: {
get() {
return this.firstName + ' ' + this.lastName
},
set(value) {
let names = value.split(' ')
this.firstName = names[0]
this.lastName = names[1]
}
}
}
})
console.log(test.computedValue)
//
// aco Yang
console.log(test.computedValue)
// acoYang ( , get )
test.computedSet = 'accco Yang'
console.log(test.computedValue)
// ( set )
// accco Yang
発見できます.Vue
の例にエージェントされた1つの属性get
メソッドを呼び出しましたが、第2回目はget
方法解決
第一のポイントはよく解決します.
Object.defineProperty
を使って代理すればいいです.次に、第二の点と第三の点を見て、依存性が変化すると、値が変化します.これは私達が以前に実現したWatcher
と似ています.属性の計算値はget
関数の戻り値です.Watcher
においても、傍受値が保存されています.この値は依存の変化によって変化します.(watcher.value
が実現した学生を見ていないなら、Watcher
とstep3
を見に行きます.)だから、属性を計算するstep4
はget
のWatcher
です.getter
のWatcher
は何ですか?ここではcallback
は必要ありません.属性の計算は依存が変化したときに保存された値だけが変化する必要があります.了解したら、私達はそれを実現します.同じように分かりやすいように、一つの種類を書きました.
function noop() {
}
let uid = 0
export default class Computed {
constructor(key, option, ctx) {
// ctx Vue
this.uid = uid++
this.key = key
this.option = option
this.ctx = ctx
this._init()
}
_init() {
let watcher = new Watcher(
this.ctx,
this.option.get || noop,
noop
)
// Vue
Object.defineProperty(this.ctx, this.key, {
enumerable: true,
configurable: true,
set: this.option.set || noop,
get() {
return watcher.value
}
})
}
}
// Vue
export class Vue extends Event {
constructor(options) {
super()
this.uid = uid++
this._init(options)
}
_init(options) {
let vm = this
...
for (let key in options.computed) {
new Computed(vm, key, options.computed[key])
}
}
}
代理属性callback
と計算属性の値を更新し、依存性が変化していない場合にも、Object.defineProperty
の更新をトリガすることなく、上記のWatcher
の問題を解決した.しかし、属性を計算するには本当にリアルタイムで対応する値を更新する必要がありますか?
まず、依存性の属性が変化すると計算属性の変化が起こることを知っています.言い換えれば、計算属性が変化すると、
3
の下の属性の一部が変化しています.data
の下の属性が変化すると、ビューの変化が生じるので、計算属性が変化してビューの変化をトリガする必要はありません.第二に、私たちは計算属性が必ず使われることを保証できません.
第1の点に基づいて、属性を計算することは、ビューの変化をトリガする必要はないので、属性を計算することは、取得時に対応する値を更新すればよい.
Watchの汚れ検査メカニズム
上記の分析によれば、
data
はComputed
の実現形態であるので、非リアルタイムアップデートWatcher
を実現したい.Watcher
において、私たちが達成した値の更新は、以下のコードによって行われる.update() {
const value = this.getter.call(this.obj)
const oldValue = this.value
this.value = value
this.cb.call(this.obj, value, oldValue)
}
更新に依存すると、この関数をトリガします.この関数はWatcher
例に保存されているWatcher
を変更しました.ですから、ここで変更する必要があります.まず、疑似コードを見てください.update() {
if(/* Watcher */){
// doSomething
// update
return
}
const value = this.getter.call(this.obj)
const oldValue = this.value
this.value = value
this.cb.call(this.obj, value, oldValue)
}
ここでの判断は最初からvalue
に教えてあげる必要がありますので、同じようにWatcher
の構造関数を変更したいです.constructor(object, getter, callback, options) {
···
if (options) {
this.lazy = !!options.lazy
} else {
this.lazy = false
}
this.dirty = this.lazy
}
Watcher
に複数の構成情報を伝達します.ここでは、リアルタイムで更新する必要がないWatcher
をoptions
と呼びます.また、このWatcher
が更新する必要があるかどうかを示すためのフラグを設定します.専門点の名前を変えるには、汚い検査が必要ですか?okこれから上の疑似コードを実現します.
update() {
// lazy Watcher
if (this.lazy) {
//
this.dirty = true
return
}
const value = this.getter.call(this.obj)
const oldValue = this.value
this.value = value
this.cb.call(this.obj, value, oldValue)
}
コードがlazy Watcher
に到達した場合、このdirty
の依存性が変化したと説明しているが、これはWatcher
であり、このupdate
は汚損検査を行う必要がある.しかし、上記のコードは
Watcher
としてマークされていますが、lazy Watcher
には変化が発生していません.関数を書いて変化をトリガする必要があります./**
*
*/
evaluate() {
this.value = this.getter.call(this.obj)
// , dirty
this.dirty = false
}
完全なWatchコードを確認します.ok
Watcher
の実装を修正します.class Computed {
constructor(ctx, key, option,) {
this.uid = uid++
this.key = key
this.option = option
this.ctx = ctx
this._init()
}
_init() {
let watcher = new Watcher(
this.ctx,
this.option.get || noop,
noop,
// Wather lazy Watcher
{lazy: true}
)
Object.defineProperty(this.ctx, this.key, {
enumerable: true,
configurable: true,
set: this.option.set || noop,
get() {
// dirty watch ,
if (watcher.dirty) {
watcher.evaluate()
}
return watcher.value
}
})
}
}
テストしてくださいlet test = new Vue({
data() {
return {
firstName: 'aco',
lastName: 'Yang'
}
},
computed: {
computedValue: {
get() {
console.log(' ')
return this.firstName + ' ' + this.lastName
}
},
computedSet: {
get() {
return this.firstName + ' ' + this.lastName
},
set(value) {
let names = value.split(' ')
this.firstName = names[0]
this.lastName = names[1]
}
}
}
})
// ( watcher get )
console.log('-------------')
console.log(test.computedValue)
//
// aco Yang
console.log(test.computedValue)
// acoYang ( , get )
test.firstName = 'acco'
console.log(test.computedValue)
// ( , get )
// acco Yang
test.computedSet = 'accco Yang'
console.log(test.computedValue)
// ( set )
// accco Yang
これまでのところ、単一Watcher
におけるデータ関連の内容はほぼ同じであり、value
、Computed
メカニズムを実現する前に、私たちは先に親子のコンポーネントを実現する必要があります.これも次のステップの内容です.クリックして関連コードを調べます.
シリーズの記事アドレス