構造
Vue$3
__data:
__ob__: Observer
dep: Dep
id: 2
subs: []
ウォッチャーに配置された潜水艦は、ウォッチャに対応する通知が更新されるトリガデータのデータ、のDEP潜水艦を変更する場合。
コード
最初の観察者の過程で登録方法は、「コレクションに依存しています。」に使用されます その閉鎖中の標的を有するDEP、このオブジェクトは、ウォッチャーオブジェクト・インスタンスを格納するために使用されます。実際には、「コレクションに依存する」プロセスは、発に対応するオブジェクトに格納されたウォッチャーのインスタンスです。データの変更は、セットはオブジェクトのは、その中にメソッドのDEP通知を通知呼び出したときに、すべてのWathcerは、ビューの更新オブジェクト、(ADDSUB)メソッドでその潜水艦に格納されている現在のウォッチャーオブジェクト(Dep.target)を作る方法を取得します。
function defineReactive (obj, key, val) {
/* 一个Dep类对象 */
const dep = new Dep();
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
get: function reactiveGetter () {
/* 将Dep.target(即当前的Watcher对象存入dep的subs中) */
dep.addSub(Dep.target);
return val;
},
set: function reactiveSetter (newVal) {
if (newVal === val) return;
/* 在set的时候触发dep的notify来通知所有的Wathcer对象更新视图 */
dep.notify();
}
});
}
class Vue {
constructor(options) {
this._data = options.data;
observer(this._data);
/* 新建一个Watcher观察者对象,这时候Dep.target会指向这个Watcher对象 */
new Watcher();
/* 在这里模拟render的过程,为了触发test属性的get函数 */
console.log('render~', this._data.test);
}
}
DEPが以下に定義し、ウォッチャー
class Dep {
constructor () {
/* 用来存放Wathcer对象的数组 */
this.subs = [];
}
/* 在subs中添加一个Watcher对象 */
addSub (sub) {
this.subs.push(sub);
}
/* 通知所有Wathcer对象更新视图 */
notify () {
this.subs.forEach((sub) => {
sub.update();
})
}
}
class Watcher {
constructor () {
/* 在new一个Watcher对象时将该对象赋值给Dep.target,在get中会用到 */
Dep.target = this;
}
/* 更新视图的方法 */
update () {
console.log("视图更新啦~");
}
}
Dep.target = null;
どのように発と関連ウォッチャーの?
掲載:なぜDep.target Watcherは、この目標を指すのだろうか?
callHook(VM、「beforeMount」)の後、マウントステージ、初期ウォッチャーへ
function noop (a, b, c) {}
// lifecycle.js
let updateComponent
updateComponent = () => {
vm._update(vm._render(), hydrating)
}
vm._watcher = new Watcher(vm, updateComponent, noop)
ウォッチャーのthis.get初期化関数の呼び出しで
var Watcher = function Watcher(vm, expOrFn, cb, options, isRenderWatcher) {
this.vm = vm;
//...
this.cb = cb;
//...
this.expression = expOrFn.toString();
//...
this.getter = expOrFn;
//...
this.value = this.lazy ? undefined : this.get();
};
Watcher.prototype.getこの時間にとのDEP出版社が接触していた、注意pushTargetは、発の目標は、このwacherに設定されている、と毎回オブジェクトが取得され、それがこのwacherに、独自のDEPプッシュを行きます。
// dep.js
export function pushTarget (_target: Watcher) {
if (Dep.target) targetStack.push(Dep.target)
Dep.target = _target
}
export function popTarget () {
Dep.target = targetStack.pop()
}
// watcher.js
Watcher.prototype.get = function get() {
pushTarget(this);
var value;
var vm = this.vm;
//...
value = this.getter.call(vm, vm);
//...
popTarget();
this.cleanupDeps();
//...
return value;
};
Watcher.prototype.getは上記また、上記の式は、実際vm._update(vm._render()、水和)で行われる、this.getter.call(VM、VM)を注意してください。当然のことながら通話
vm._render()メソッドの呼び出しが見つかりましたVMをデバッグ、VNODEを返します。$ Options.renderの事実、
Vue.prototype._render = function () {
// ...
var vm = this;
var ref = vm.$options;
var render = ref.render;
vnode = render.call(vm._renderProxy, vm.$createElement);
// ...
return vnode
}
// 而render方法其实就是用于输出一个虚拟节点
(function anonymous(
) {
with(this){return _c('div',{attrs:{"id":"app"}},[(message + 1 > 1)?_c('div',[_v(_s(message + 1))]):_e(),_v(" "),_c('button',{on:{"click":function($event){message += 1}}},[_v("阿道夫")])])}
})
vm._updateへのその後の結果
Vue.prototype._update = function(vnode, hydrating) {
var vm = this;
var prevEl = vm.$el;
var prevVnode = vm._vnode;
// ...
vm._vnode = vnode;
// ...
vm.$el = vm.__patch__(prevVnode, vnode);
// ...
};
結論はウォッチャー初期段階をマウントされ、その後、コールwathcer初期化は、get pushTargetで(この)、および独自のゲッターを実行するためには、コンテンツの表現で取得した後、式があるvm._update(vm._render(), hydrating)
ため、機能が実行を開始するレンダリング、仮想出力される機能をレンダリングノード。