vue源码之入口文件解析

由于项目中经常使用vue,所以这次趁有机会赶紧拜读下源码,体验下vue源码的设计风采。


一、下载源码

Github地址:https://github.com/RiversCoder/vue

二、源码项目目录

vue源码之入口文件解析_第1张图片

三、加载core内核入口文件index.js

 

vue源码之入口文件解析_第2张图片


通过看源码我们可以得知这个入口文件:

(1)引入了几个对象,包括Vue构造方法
(2)初始化全局API : initGlobalAPI(Vue)
(3)三个属性拦截器,其中两个拦截监听Vue.prototype,另一个拦截监听Vue
(4)定义vue的版本
(5)导出Vue构造方法

四、加载Vue定义的文件index.js

vue源码之入口文件解析_第3张图片


1.通过观察源码,我们可以发现:
(1)引入了一些需要Vue这个构造方法的方法
(2)Vue构造方法中调用初始化方法 this._init(options)
(3)将Vue转为参数,向引入的函数中传递
(4)将Vue默认导出

2.解析核心函数:

function Vue (options) {
  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)
}

(1)这个构造方法决定了调用的方式

let vm = new Vue({ //选项 });

(2)if 判断是否用new关键字实例化Vue,否则报错
(3)初始化方法this._init(options) ,将options对象(data,props,methods,filters … )当参数传递
(4)调用方法:

initMixin(Vue)
stateMixin(Vue)
eventsMixin(Vue)
lifecycleMixin(Vue)
renderMixin(Vue)

注:所以_init(obj)方法则是在这些方法中定义

五、解析初始化文件instancce/init.js

vue源码之入口文件解析_第4张图片

1.init.js文件中有一个很重要的方法initMixin,这个方法的作用是将vm所需的各种初始化变量与函数混入到vm对象中
2.函数的开头主要定义了一些属性和标记,然后合并选项,合并选项的条件如下:

if (options && options._isComponent) {
  initInternalComponent(vm, options)
} else {
  vm.$options = mergeOptions(
    resolveConstructorOptions(vm.constructor),
    options || {},
    vm
  )
}


(1)且先看if条件,当options存在并且options._isComponent为true时,就会调用initInternalComponent(vm, options)
(2)options._isComponent 用来记录当前options是否属于组件。而initInternalComponent()从函数名看,其作用应当是初始化内部组件。
(3)如果,当options属于一个组件时,就对内部组件(internal component)进行初始化。
(4) 否则,将传入的options与vm本身的属性进行了合并,并重新赋值给vm.$options。
(5)结果,Vue实例会将传入的用户自定义options合并到自身属性中。

3. 然后初始化代理

/* 初始化代理 */
if (process.env.NODE_ENV !== 'production') {
  initProxy(vm)
} else {
  vm._renderProxy = vm
}

4. 把自身的实例给暴露出来,传递给其他方法,为Vue的实例添加各种接口,事件,以及可调用的属性

vm._self = vm
initLifecycle(vm)
initEvents(vm)
initRender(vm)
callHook(vm, 'beforeCreate')
initInjections(vm) // resolve injections before data/props
initState(vm)
initProvide(vm) // resolve provide after data/props
callHook(vm, 'created')

解析:callHook(vm, 'beforeCreate')、callHook(vm, 'created')

说明在beforeCreate生命周期前需要执行:initLifecycle(),initEvents (),initRender();而在created生命周期前需要执行initInjections(),initState(),initProvide();


5. Dom挂载

/* 当el存在时,将其挂载到vm实例上 */
if (vm.$options.el) {
  vm.$mount(vm.$options.el)
}


六、初始化生命周期文件instance/lifecycle.js

vue源码之入口文件解析_第5张图片

1.这个文件主要定义了vue的生命周期相关的初始化方法
2.核心方法 iniflifecycle( ) 解析

let parent = options.parent
if (parent && !options.abstract) {
  while (parent.$options.abstract && parent.$parent) {
    parent = parent.$parent
  }
  parent.$children.push(vm)
}

vm.$parent = parent
vm.$root = parent ? parent.$root : vm

(1)在方法的开头逐级查找到以第一个非抽象的父级,如果 parent.$parent存在 且 parent.$options.abstract 为真,再次往上寻找
(2)从当前Vue实例vm开始向上查找,找到最近的一级abstract为false的parent。将vm push给它的$children
(3)将vm的parent修改为上一步中找到的parent
(4)修改vm的根$root。若vm的parent存在,则与parent的$root统一;否则$root就是vm自身
(5)修改vm的各种变量
(6)结果:经过initLifecycle(),vm的parent,以及parent的children,都得到了更新。同时为vm新增了各种变量

七、其他混入方法

stateMixin(Vue) // 混入props,methods,data,computed,watch
eventsMixin(Vue) // 混入_events,并更新组件的listeners
lifecycleMixin(Vue) // 混入_vnode,$el,$parent相关
renderMixin(Vue) // 混入渲染相关的内容,如$slots等

经过这些翻方法的混入,Vue由一个空对象,变为拥有一堆变量与函数的庞大对象

 

八、全局初始化src/core/golbal-api.js

1.在initGlobalAPI方法中的开头,主要实现了一个configDef对象的config属性的拦截监听

// config
const configDef = {}
configDef.get = () => config
if (process.env.NODE_ENV !== 'production') {
  configDef.set = () => {
    warn(
      'Do not replace the Vue.config object, set individual fields instead.'
    )
  }
}

/* 监听config属性值得变化 */
Object.defineProperty(Vue, 'config', configDef)

2.为Vue的util设置了几个成员,包含 :warn,extend,mergeOptions,defineReactive 且暴露出去3.为Vue设置了set,delete,nextTick,以及一个空的options。其中options按类型填充默认空对象

Vue.set = set
Vue.delete = del
Vue.nextTick = nextTick

Vue.options = Object.create(null)
ASSET_TYPES.forEach(type => {
  Vue.options[type + 's'] = Object.create(null)
})

4.将 options.components 与 builtInComponents 合并

extend(Vue.options.components, builtInComponents)

5.初始化use,mixin,extend,assetRegisters全局方法

initUse(Vue)
initMixin(Vue)
initExtend(Vue)
initAssetRegisters(Vue)

 

你可能感兴趣的:(前端框架,javascript,vue)