VUE依存コレクションコード解析

構造

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)ため、機能が実行を開始するレンダリング、仮想出力される機能をレンダリングノード。

おすすめ

転載: www.cnblogs.com/everlose/p/12542023.html