本文是作者在学习vue底层逻辑时的总结与反思,记录下来供大家讨论与研究,如有不足可评论区指出,共同进步。
本文注重new vue时vue底层逻辑的梳理,重点在于在全局上掌握vue都干了什么,故不会对过程中涉及的函数全部进行介绍,只针对核心逻辑
那么,我们就开始吧!
说到new vue的时候vue都干了什么,首先,我们的知道vue到底是个什么东西?
当然,在这里我想说的是:在vue的源码种,他到底是个什么?为了解决这个疑惑,我们唯一的办法就是去看vue的底层源码,首先,我们每次使用vue的时候,都免不了一句话:
import Vue from vue
想找到vue的真面目,我们就要从这里开始下手,以Runtime + Compiler 构建出来的 Vue.js为例来分析,首先,在vue源码种,他的入口文件是: (具体vue源码目录设计及规范可以下载源码查看)
src/platforms/web/entry-runtime-with-compiler.js
在这个文件下又引入了
import Vue from './runtime/index'
打开runtime目录下的index.js文件,发现它又有一层引入
import Vue from 'core/index'
继续打开core目录下的index.js文件,会发现
import Vue from './instance/index'
这里进行了再一次的引入,打开instance目录下的index.js文件:
import { initMixin } from './init'
import { stateMixin } from './state'
import { renderMixin } from './render'
import { eventsMixin } from './events'
import { lifecycleMixin } from './lifecycle'
import { warn } from '../util/index'
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)
}
initMixin(Vue)
stateMixin(Vue)
eventsMixin(Vue)
lifecycleMixin(Vue)
renderMixin(Vue)
export default Vue
终于,我们找到了vue的庐山真面目,先纵观整个文件,我们可以发现文件逻辑并不复杂,首先引入了很多的MIXin文件,然后用function定义了一个类,名字就叫做vue,里面的逻辑是判断了一下环境变量,然后调用this._init方法,对一些options进行了初始化。
到这里大家应该就恍然大悟了,原来vue就是一个用function声明的类啊!相信大家听到类这个字,第一个想到的应该就是class,为什么vue不使用class来声明一个类呢?同时也有疑问,为什么一个类的定义要引用嵌套这么多层呢?
这里贴一段尤雨溪被采访时说的话:
随着用力的推广,Vue开始用于一些更长期的项目。这种情况下,一些短期内方便的功能变得难以维护。所以Vue在轻量和功能之间也发生了变化,从一开始的强调速度,简单上手,到后面的注重用户代码的可维护性,避免用户自己掉到自己写出来的陷阱里,一直在不断地转化。最终的目标是找到一个比较良好的平衡点,维持简易上手的良好体验,同时尽可能地避免一时的便易影响长期的可维护性。
也就是说,尤雨溪在设计vue的时候,希望他有更好的可维护性,这就使得他在定义vue类的时候,在不同文件中层层引用,目的就是让vue每通过一个文件,就在其原型上拓展一些新的方法。不同的文件做不同的任务,这就使得代码逻辑更加清晰。
之所以使用function创建vue类,是因为在vue文件里,有很多的mixin函数,这些函数都把vue作为参数传入,vue按功能把这些拓展发散到不同模块去实现,而这一点则是class难以具备的。
至此为止,我们已经了解了vue到底是什么,其实他就是一个用function定义的类,然后在其原型上拓展了一些方法,既然vue是一个类,那么我们在实例化这个类的时候,具体又做了哪些事情呢?我们且听下回分解。