Appearance
new Vue到底都干了啥呢?🙄
很多时候我们都会被问到new Vue到底发生了肾么事?这篇文章我们就来好好的看看!!!😁
首先我们从源码调试开始
之前有一篇文章提到了vue源码调试,可以移步至此。
入口文件
当执行run dev时,我们可以根据package.json中配置拿到相应的参数
"dev": "rollup -w -c scripts/config.js --sourcemap --environment TARGET:web-full-dev",
此时我们可以拿到一个路径scripts/config.js
和参数TARGET:web-full-dev
在scripts/config.js
文件中可以看到定义的builds对象找到web-full-dev
对应的属性值 这时找到了入口文件src\platforms\web\entry-runtime-with-compiler.js
入口文件干了啥?
从上面的代码可以看出拓展了$mount
,接着就是根据传入的参数el获取dom元素。然后判断有没有render
,如果没有render
则去找template
,如果没有template
则根据函数getOuterHTML
将el
内部内容作为template
,所以我们可以得出结论,render template el
的优先级是 render > template > el
。如果template
则需要函数compileToFunctions
将template
编译得到一个render
函数,并把render
设置到组件选项上。最后执行了mount
方法的默认任务。
接下来正式进入主题
寻找构造函数Vue
在入口文件中可以看到从./runtime/index
文件导入Vue
,进入此文件。 可以看到core/index
文件中导入的Vue
,还可以看到实现了$mount
方法。
进入文件core/index
可以看到从./instance/index
中导入了Vue
,而且执行了一个全局Api初始化方法initGlobalAPI
,继续进入./instance/index
终于找到了Vue
构造函数。在Vue
构造函数中执行了_init
方法。下面也执行了一系列的混入。可以在initMixin
中找到_init
方法。下面我们来看看_init
方法到底干了什么。
构造函数中的_init干了啥?
这里我们可以很清楚的看到这一系列的流程。属性的合并接着是各种初始化。
initLifecycle
-> 定义了$parent
、$children
、$root
、$ref
initEvent
-> 对于一些自定义事件的监听initRender
-> 定义了$slots
、$createElement
, 让$attrs
$listeners
变成响应式的- 执行生命周期
beforeCreate
initInjections
-> 获取祖辈注入的数据initState
-> 数据初始化:data
、props
、methods
、computed
、watch
initProvide
-> 将数据提供给后代- 执行生命周期
created
- 执行挂载
如何挂载
回到刚刚提到的实现了$mount
方法的文件core/index
这里返回了一个从文件core/instance/lifecycle
函数mountComponent
在执行这个函数之前首先是执行的是我们拓展的$mount
函数,在那里可以拿到render
。在mountComponent
中执行了beforeMount
钩子,然后new Watcher
执行updateComponent
函数。这个函数主要做的事情就是通过_render()
函数把render
变成虚拟dom,通过_update
把虚拟dom变成真实dom插入到试图中,最后执行mount
钩子函数
总结
以上大概就是我理解的new Vue干了一系列的操作,如有需要改进的地方,欢迎留言哦~~~最后来个思维导图