Vue源码学习之初始化模块init.js解析
我们看到了VUE分了很多模块(initMixin()stateMixin()eventsMixin()lifecycleMixin()renderMixin()),通过使用Mixin模式,都是使用了JavaScript原型继承的原理,在Vue的原型上面增加属性和方法。我们继续跟着this._init(options)走,这个一点击进去就知道了是进入了init.js文件是在initMixin函数里面给Vue原型添加的_init方法。首先来从宏观看看这个init文件,可以看出主要是导出了两个函数:initMixin和resolveConstructorOptions,具体作用我们一步步来讨论。咋的一看这个文件,可能有些童鞋会看不明白函数参数括号里面写的是什么鬼,这个其实是应用了flow的类型检查,具体flow的使用这里就不介绍了,有兴趣的请移步:https://flow.org/en/ 我们现在来看第一个函数initMixin,Vue实例在初始化的时候就调用了这个函数, export function initMixin (Vue: Class
Vue.prototype._init = function (options?: Object) { const vm: Component = this // a uid vm._uid = uid++ let startTag,endTag // a flag to avoid this being observed / istanbul ignore if / if (vm.$options.el) { 我们本着宏观简化原则,这个函数里面前面有三个if判断工作我们可以先不细化讨论,大致第一个是用performance做性能监测,第二个合并option,第三个是做代理拦截,是ES6新特性,可参考阮一峰大神关于proxy的介绍【http://es6.ruanyifeng.com/#docs/proxy】。那么就进入了初始化函数主要点: if (vm.$options.el) {
vm.$mount(vm.$options.el) } 这里来一个插曲start V2.1.8及以前的版本】这里比较方便理解在生命周期created之后再做render,那么在created之前就无法获取DOM。这也是在有些源码解析文章里面很容易见到的分析,也是正确的 v2.1.9及以后的版本】但到这里一开始就懵逼了很久render提到beforeCreate之前去了,那岂不是DOM在beforeCreate之前就能获取到了?显然不对了,请注意render虽然提前了,但是后面多了一个if这个if里面才获取DOM的关键,这个if在2.1.8版本之前是在render函数里面的,在2.1.9之后被提出来,然后render函数提前了,至于为何提前暂未了解,此处只是踩了一个看其他源码解析不同版本带来的坑! 插曲end,继续 1.initLifecycle// locate first non-abstract parent
let parent = options.parent //我理解为父实例或者父组件 if (parent && !options.abstract) { //例子中没有parent,断点代码的时候自动跳过 while (parent.$options.abstract && parent.$parent) { parent = parent.$parent } parent.$children.push(vm) } vm.$parent = parent vm.$children = [] vm._watcher = null 这个函数主要是有父实例的情况下处理vm.$parent和vm.$children这俩个实例属性,我此处没有就跳过,其他的就是新增了一些实例属性 2.initEvents又新增两个属性,后面那个if条件里面是有父组件的事件时初始化,估计就是props和events父子组件通信的事件内容。 3.initRender createElement(vm,a,d,false)
vm.$createElement = (a,true)
const parentData = parentVnode && parentVnode.data
/* istanbul ignore else */
if (process.env.NODE_ENV !== 'production') {
defineReactive(vm,'$attrs',parentData && parentData.attrs,() => {
!isUpdatingChildComponent && warn(`$attrs is readonly.`,vm)
},true)
defineReactive(vm,'$listeners',vm.$options._parentListeners,() => {
!isUpdatingChildComponent && warn(`$listeners is readonly.`,true)
} else {
defineReactive(vm,null,true)
}
}
此函数也是初始化了节点属性信息,绑定createElement函数到实例【并未挂载】,接下来调用beforeCreate回调钩子;——TODO1:后续专题分析VUE渲染逻辑 4.initInjections {
/* istanbul ignore else */
if (process.env.NODE_ENV !== 'production') {
defineReactive(vm,key,result[key],() => {
warn(
`Avoid mutating an injected value directly since the changes will be ` +
`overwritten whenever the provided component re-renders. ` +
`injection being mutated: "${key}"`,vm
)
})
} else {
defineReactive(vm,result[key])
}
})
observerState.shouldConvert = true
}
}
此函数也是当有inject属性时做处理,源码例子无inject断点跑暂时跳过 5.initState可以看出此处是对options传入的props/methods/data/computed/watch属性做初始化————TODO2:分析每个属性的初始化 6.initProvide这个函数跟4.initInjections在同一个inject.js中,也是在传入参数有provide属性时做处理,暂时跳过,然后就到了created回调钩子,最后的vm.$mount接入TODO1; 今天initMixin到此结束,以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程之家。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- Oracle指定某些值排最前或最后
- 名称空间 – 使用xmlns名称空间的GDataXML写入文件
- ArcGIS Server + ArcSDE + PostgreSQL + ArcMap安装(windo
- ruby-on-rails – DelayedJob错误:程序中已经有一个或多个
- c# – 右键单击??并选择程序,在文件夹上运行.net程序
- frameworks\base\packages\SettingsPro
- C++实现遗传算法
- 如何在C#中的字符串集合编辑器中添加组合框项值?
- JSON.parse()和JSON.stringify()
- vue-cli初始化项目中使用less的方法