先看别人绘制的图
image
我的手绘图
image
其实一共是3+1+view渲染模块
3:
observer:监听器 vue2.0 用Object.defineProty、vue3.0 用proxy
watcher:订阅器
compile:解析器
Dep:订阅器收集器
view:渲染dom

通过看图,先找有几条通路
a、observer-->Dep-->watcher-->view
b、compile-->watcher-->Dep
c、compile-->view

c路径是最简单的,c主要实现是解析指令如v-model等,初始化到view视图层。

b路径compile-->watcher 形成初始化的订阅器,watcher-->Dep订阅器被添加到订阅器容易里,这里实际是在observer 阶段eg:vue2.0的Object.defineProty的get方法的时候被添加的,但为何没有observer这个回路呢?设计者用了一个兼容的写法,强制执行了data监听器的observer方法里Object.defineProty的get方法。

a路径observer-->Dep-->watcher 是通知变化,此阶段eg: vue2.0的Object.defineProty的set方法触发的,最后watcher-->view 变化反应到view层

不难发现,到能到底view层的就只有complie和watcher,一个是模板初始化到view层,一个是update后更新到view层。不管是哪条路径到达view层实际都是对dom进行原生事件的操作(watcher是在第三个参数回调函数里更改view)
如:

node.textContent = typeof value == 'undefined' ? '' : value;

具体看看watcher大致实现:

function Watcher(vm, exp, cb) { 
      this.cb = cb; 
      this.vm = vm;  // vm data对象
      this.exp = exp;  // exp data对象的键key
      this.value = this.get();  // 将自己添加到订阅器的操作
}
 
Watcher.prototype = {
    update: function() {
       this.run();
    },
    run: function() { 
       var value = this.vm.data[this.exp]; 
       var oldVal = this.value; 
       if (value !== oldVal) { 
         this.value = value; 
         this.cb.call(this.vm, value, oldVal);
       }
    },
    get: function() {
        Dep.target = this;  // 缓存自己
        var value = this.vm.data[this.exp]  // 强制执行监听器里的get函数
        Dep.target = null;  // 释放自己
        return value;
    }
};

理解了这个回路,然后再逐一去理解回路实现的逻辑就很容易理解和记忆了。


健儿
79 声望4 粉丝

掌握好原生js。