vue源码学习之初始化过程

初始化过程

初始化过程:init -> $mount -> compile -> new Watcher -> render -> update
在这里插入图片描述

  1. src/platforms/web/runtime/index.js:实现$mount
  2. src/core/index:全局api
  3. src/core/instance/index:声明vue构造函数
  4. src/platforms/web/entry-runtime-with-compiler:覆盖了$mount
  5. src/core/instance/lifecycle.js mountComponent:执行渲染和更新,虚拟dom -》真实dom

1、定义$mount,patch

src/platforms/web/runtime/index.js
执行挂载方法

Vue.prototype.__patch__ = inBrowser ? patch : noop // 定义一个补丁函数,执行patching算法进行更新

Vue.prototype.$mount = function (  // 定义一个$mount 方法 (挂载根组件到指定宿主元素)
  el?: string | Element,
  hydrating?: boolean
): Component {
  el = el && inBrowser ? query(el) : undefined
  return mountComponent(this, el, hydrating) // 执行挂载
}

2、定义全局api

src/core/index.js

initGlobalAPI(Vue)

// src/core/global-api/index.js
Vue.set = set
Vue.delete = del
Vue.nextTick = nextTick
initUse(Vue) // 实现Vue.use函数
initMixin(Vue) // 实现Vue.mixin函数
initExtend(Vue) // 实现Vue.extend函数
initAssetRegisters(Vue) // 注册并实现指令,组件,过滤器

3、定义Vue构造函数

src/core/instance/index.js

function Vue (options) { // vue构造函数
  if (process.env.NODE_ENV !== 'production' &&
    !(this instanceof Vue)
  ) {
    warn('Vue is a constructor and should be called with the `new` keyword')
  }
  this._init(options) // 初始化
}
initMixin(Vue) // 实现_init函数
stateMixin(Vue) // 状态相关api,$data,$props,$set,$delete,$watch
eventsMixin(Vue) // 事件相关api,$on,$once,$off,$emit
lifecycleMixin(Vue) // 生命周期,_update,$forceUpdate,$destory
renderMixin(Vue) // 渲染api, _render,$nextTick

src/core/instance/init.js
实现initMixin()方法,创建组件实例,初始化数据、属性以及事件等等。

export function initMixin (Vue: Class<Component>) { // 创建组件实例,初始化其数据、属性和事件等等
  Vue.prototype._init = function (options?: Object) { // 在Vue原型中添加_init方法
  ...
  	initLifecycle(vm) // 定义了$parent,$root,$children,$refs,
    initEvents(vm) // 处理父组件传递的监听器($on,$emit)
    initRender(vm) // $slots,$scopedSlots,_c,$createElement
    callHook(vm, 'beforeCreate') // 在beforeCreate生命周期之前执行了以上三个方法
    initInjections(vm) // resolve injections before data/props  获取注入数据
    initState(vm) // 初始化props,methods,data,computed,watch
    initProvide(vm) // resolve provide after data/props  注入数据
    callHook(vm, 'created')
    ...
  }
 }

4、入口

src/platforms/web/entry-runtime-with-compiler.js
这个文件主要是扩展了$mount的方法,用于处理template和el选项,同时将获取的模板进行编译。

const mount = Vue.prototype.$mount // 获取Vue原型中的 $mount 方法
Vue.prototype.$mount = function ( // 添加一个处理template或者el选项的功能
  el?: string | Element, // el 属性其实就是挂载点,所有的挂载元素会被Vue生成的DOM替换掉,如果render跟template都不存在,那么挂载元素的html就会被拿出来当作模板使用。
  hydrating?: boolean
): Component {
  el = el && query(el) // 查找对应的dom,没有就自己创建一个div
  const options = this.$options // 获取Vue实例中的参数
  if (!options.render) { // 如果不存在render函数,
  //因此可以看到render的优先级高于template高于el
  	let template = options.template // 才去找template
  ...
  ...
    // 获取模板后执行编译
    //compileToFunctions() 将template字符串转换成render函数
    const { render, staticRenderFns } = compileToFunctions(template, { // 编译模板
        outputSourceRange: process.env.NODE_ENV !== 'production',
        shouldDecodeNewlines,
        shouldDecodeNewlinesForHref,
        delimiters: options.delimiters,
        comments: options.comments
      }, this)
      options.render = render // 将render函数保存的options中
      options.staticRenderFns = staticRenderFns
      ...
  }
  return mount.call(this,el,hydrating)
}

无论通过template还是el的方式最终生成的都是render函数。

5、mountComponent

src/core/instance/lifecycle.js

export function mountComponent ( // 执行挂载
	...
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章