Dep类是用来将数据和watcher关联起来的一个类。

var uid = 0;

var Dep = function Dep () {
  this.id = uid++;
  this.subs = [];
};

// 添加对某个watcher的关联
Dep.prototype.addSub = function addSub (sub) {
  this.subs.push(sub);
};

// 解除对某个watcher的关联
Dep.prototype.removeSub = function removeSub (sub) {
  remove(this.subs, sub);
};

// dep和watcher相互关联的入口
Dep.prototype.depend = function depend () {
  // Dep.target 期望存放watcher实例
  if (Dep.target) {
      // watcher添加对dep的关联,同时在内部调用dep的addSub方法,添加dep对watcher的关联
    Dep.target.addDep(this);
  }
};

// 通知watcher数据更新
Dep.prototype.notify = function notify () {
  var subs = this.subs.slice();
  for (var i = 0, l = subs.length; i < l; i++) {
    subs[i].update();
  }
};

每一个dep实例都会有一个唯一的id,这个唯一标示会在watcher实例中用到。dep实例的核心是subs字段,它维护一个watcher队列,当时据变化时通知watcher数据更新(notify方法)。

deps和watcher是相互关联的,可以想到watcher也会维护一个deps队列。dep和watcher建立联系的入口是depend方法,你可能会好奇为什么要有这么个入口,你可能试着去掉depend方法然后把相互关联功能放到addSub方法中:

Dep.prototype.addSub = function(){
  var watcher = Dep.target;
    if(!watcher){
        return;
    }
    // 判断watcher是否关联到了dep
    if(watcher.deps.indexOf(this)===-1){
        watcher.deps.push(this);
    }
    // 判断dep是否关联到了watcher
    if(this.subs.indexOf(watcher)===-1){
        this.subs.push(watcher);
    }
}

这么做确实可行,但是这么做时间上比较吃亏(判断是否建立了关系需要O(n)),所以作者把是否建立了联系这个判断放在了watcher中,利用集合实现(时间O(1))。

Watcher.prototype.addDep = function addDep (dep) {
  // newDepIds和depIds都是集合
  var id = dep.id;
  // 判断watcher是否关联到了dep
  if (!this.newDepIds.has(id)) {
    this.newDepIds.add(id);
    this.newDeps.push(dep);
    // 判断dep是否关联到了watcher
    if (!this.depIds.has(id)) {
      dep.addSub(this);
    }
  }
};

results matching ""

    No results matching ""