阅读 82

vue-组件挂载mount

组件mount挂载的过程,是将模板转为render函数,通过render生成虚拟dom,然后再转为真实dom过程

组件挂载时间节点

当通过new Vue初始化实例vm时,会执行_init方法。此时,如果传参中包含el|template|render,会执行$mount进行挂载

Vue.prototype._init = function(opts) {
    ...
    if(vm.$options.el) {
      vm.$mount(vm.$options.el)
    }
 }
复制代码

$mount

在vue的原型上添加$mount,进行组件的挂载。在进行挂载时,如果用户没有传递render参数,需要将el|template先转为render函数;其次执行mountComponent方法

Vue.prototype.$mount = function(el) {
    const vm = this;
    const options = vm.$options;
    el = document.querySelector(el);
    if (!options.render) {
      let template = options.template;
      if(!template && el) {
        template = el.outerHTML;
      }
      const render = compileToFunction(template);
      options.render = render;
    }
   
    mountComponent(vm, el)
}
复制代码

mountComponent组件更新函数

在组件更新函数中,先通过_render将render的模板编译结果转为虚拟dom,然后通过_update将虚拟dom转为真实dom。创建watcher实例,将组件更新函数作为参数传递;在watcher的constructor中执行组件更新函数,实现组件的挂载

function mountComponent(vm, el){
  const options = vm.$options
  vm.$el = el;
  let updateComponent= () => {
    vm._update(vm._render());
  }
  new Watcher(vm, updateComponent, () => {}, true);
}
复制代码

watcher

class Watcher{
  constructor(vm, exprOrFn, callback=()=> {}, options={}){
    this.vm = vm
    this.exprOrFn = exprOrFn
    if (typeof exprOrFn === 'function') {
      this.getter = exprOrFn
    }
    this.callback = callback
    this.options = options
    this.id = id++;
    this.get(); // 创建watcher 默认会调用自身的get方法,执行Vue._update方法,将虚拟dom转为真实dom
  }
  get () {
    this.getter();
  }
}
复制代码