Vue源码阅读之Vue构造函数(⼀)
前端技术⽇新⽉异,过⼀段时间就会涌现⼀些新的技术框架或者概念。并且⽬前使⽤最⼴泛的三⼤前端库,也不断地在更新版本增加新特性。对于前端开发⼈员来说,都有种学不动的⽆⼒感,还要⾯对来⾃“后浪”的挑战。因此提升技术的深度和⼴度,是塑造⾃我核⼼竞争⼒的关键⼀步。今天咋们就来阅读理解Vue的源码,知道我们平时在开发过程中经常使⽤的属性、⽣命周期以及数据双向绑定的实现机制。vuejs流程图插件
⼀、项⽬结构
⾸先我们需要将Vue源码从上拉倒本地,现在最新版本的Vue加⼊了typescript类型检测。我们都知道javascript是弱类型语⾔,书写代码的时候没有对变量的类型进⾏定义,后期扩展、团队开发中很容易犯错。⼤家还不了解typescript可以先看,不然源码中的语法会存在⼀定的阅读障碍。
项⽬中我们重点关注src下⾯的complier(编译相关)、core(核⼼代码逻辑)、platforms(平台相关)这三部分内容,基本涵盖了平常⼯程化开发中所⽤到的知识的底层原理。
如果需要在本地对源码进⾏断点调试,可以按照下图进⾏配置:
运⾏npm run dev命令后,会在dist⽬录下⽣成未压缩、混淆的vue.js⽂件。引⽤该⽂件就能在源码上打断点调试了。
⼆、定义Vue构造函数
core/instance/index.js中定义了Vue构造函数并暴露出去,属于原⽣javascript⾯向对象编程思想,结合⼯⼚模式和原型链模式实现继承。
在代码中我们会看到许多process变量,这个属于node.js中的对象,根据打包命令能判断环境变量区分开发环境、⽣产环境,继⽽⾛不同的代码逻辑。
Vue函数体中执⾏了_init⽅法,根据实例化vue传⼊的options不同⽣成不同的对象,_init⽅法在initMixin后进⾏了混⼊。
下⾯的⼏个mixin⽅法,就是在Vue对象的原型上混⼊公共⽅法,包括初始化、state数据、事件处理、⽣命周期、render。
三、_init⽅法
core/instance/init.js⽂件中我们看到_init⽅法定义在Vue.prototype原型上。函数体中排除process对于环境变量的判断,其实代码量不是很多。
这部分代码判断vue实例是否是组件,不是组件就将传⼊的options在内部进⾏合并,保留vm对象的完整性。
这部分就会初始化⽣命周期、事件、渲染页⾯、state数据。callHook⽅法⽤于调⽤组件内部相应的⽣命周期钩⼦,看到这⾥我们就很好理解为什么组件中created钩⼦是在页⾯数据初始化之后进⾏调⽤,并且inject数据在data/props之前就能获取到。
最后就是将vue实例$mount挂载到对应的dom节点上。
四、callHook函数
core/instance/lifecycle.js中看到callHook这个⽅法接受两个参数vm、hook,会获取options参数中传⼊的对应钩⼦的执⾏函数。然后通过invokeWithErrorHandling这个⽅法进⾏处理。
invokeWithErrorHandling⽅法定义在core/util/error.js中,核⼼逻辑就是红框中标注的部分,在vm实例对象上通过apply、call进⾏调⽤执⾏。并且钩⼦函数本⾝就是promise,也会返回promise对象,可以通过catch进⾏错误捕获。
现在看来,⽣命周期中的钩⼦函数,相当于在组件进⾏特定操作后,⽐如:数据初始化、dom重绘、组件销毁等,Vue库内部提供的可以在⾃定义组件中进⾏副作⽤操作的钩⼦。⾄于数据更新如何改变虚拟dom,继⽽触发页⾯重绘的逻辑,都是在框架内部进⾏处理的。
五、initState初始化组件数据
core/instance/state.js中initState函数会初始化props、methods、data、computed、watch这⼀系列属性。我们重点看initData这个⽅法的逻辑、
先是获取options上的data对象,判断是否是函数然后⾛不同的逻辑,并且将数据赋值给vm._data私有变量。
接下来这段代码就很重要,有⼏个作⽤:
1. hasOwn判断methods、props中是否有同名属性;
2. props中如果没有同名的属性,isReserved⽅法判断变量名是否以“$”、"_"两个特俗字符开头,这两个属于特定字符适⽤于在类中定义
私有属性;
3. proxy⽅法通过Object.defineProperty(target, propKey, propDesc)⽅法将vm.optios.data上的数据做了⼀层代理。能直接在vm对象对象
上进⾏set赋值、get取值操作;
最后observe是new Observer(value)的实例,是基于Vue实现了观察者模式,监听数据变化,更新vNode重绘UI页⾯。有兴趣的同学可以看看这篇⽂章
我⽬前是通过定义Vue构造函数->_init()->initState()->initData()这⼀条线来阅读源码。诚然⾥⾯的知识点、细节很多,需要花时间钻研!最后上⼀张流程图:
系列相关⽂章:
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论