Vue源码分析--vm.$mount()

Vue源码分析–vm.$mount(el)

将Vue对象挂载到指定页面元素上,下面是一些使用时的注意点

    new Vue(options)时会根据模板生成一个vnode对象,再以vnode生成一个Element对象 new Vue(options)时,如果存在options.el,则会用生成的Element对象替换掉页面上的el 如果不存在options.el,则需手动挂载 vm.$mount(el) 如果已挂载el,则无法挂载其他el 如果new Vue(options)时不存在模板,则会以手动挂载对象 vm.$mount(el)中的el为template

然后是源码分析,我把那些异常处理相关的代码去掉了

Vue.prototype.$mount = function (
  el?: string | Element,
  hydrating?: boolean // 一直没弄明白这个参数是干嘛的
): Component {
          
   
  // 如果当前环境是浏览器环境,获取el节点
  el = el && inBrowser ? query(el) : undefined
  return mountComponent(this, el, hydrating)
}

query(el)

根据传入的el元素,生成对应的Element对象

/**
 * 如果el传Element元素,直接返回
 * 否则返回 document.querySelector(el) 或者 document.createElement(div)
 */
export function query (el: string | Element): Element {
          
   
  if (typeof el === string) {
          
   
    const selected = document.querySelector(el)
    if (!selected) {
          
   
      return document.createElement(div)
    }
    return selected
  } else {
          
   
    return el
  }
}

mountComponent(vm, el, hydrating)

vm.$mount中的核心方法,绑定更新方法,执行生命周期

export function mountComponent (
  vm: Component,
  el: ?Element,
  hydrating?: boolean
): Component {
          
   
  // 将传入的 el 赋值给 vm.$el
  vm.$el = el
  if (!vm.$options.render) {
          
   
    vm.$options.render = createEmptyVNode
  }
  // 执行生命周期 beforeMount 回调,以及 hook:beforeMount,后面同理
  callHook(vm, beforeMount)

  let updateComponent = () => {
          
   
    // vm._render() 创建并返回 VNode
    // vm._update() 接受 VNode 将其转为真实节点,并替换 vm.$el
    // 后续再分析 vm._render 与 vm._update 这两个方法
    vm._update(vm._render(), hydrating)
  }

  // 监控 执行updateComponent()时 所依赖的属性;如果有变化,执行 updateComponent()
  new Watcher(vm, updateComponent, noop, {
          
   
    // 执行 updateComponent() 前,执行before
    before () {
          
   
      // new Watcher()时,也会执行一遍updateComponent(),
      // 所以如果没有执行过 mounted 生命周期,就没有 beforeUpdate
      if (vm._isMounted && !vm._isDestroyed) {
          
   
        callHook(vm, beforeUpdate)
      }
    }
    // 为true时,赋值 this._watcher = 当前new 出来的这个实例
    // 为$forceUpdate做准备
  }, true)
  
  hydrating = false

  // 如果当前vm没有虚拟节点,执行mounted生命周期
  if (vm.$vnode == null) {
          
   
    vm._isMounted = true
    callHook(vm, mounted)
  }
  return vm
}
经验分享 程序员 微信小程序 职场和发展