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、$refinitEvent-> 对于一些自定义事件的监听initRender-> 定义了$slots、$createElement, 让$attrs$listeners变成响应式的- 执行生命周期
beforeCreate initInjections-> 获取祖辈注入的数据initState-> 数据初始化:data、props、methods、computed、watchinitProvide-> 将数据提供给后代- 执行生命周期
created - 执行挂载
如何挂载
回到刚刚提到的实现了$mount方法的文件core/index这里返回了一个从文件
core/instance/lifecycle函数mountComponent在执行这个函数之前首先是执行的是我们拓展的
$mount函数,在那里可以拿到render。在mountComponent中执行了beforeMount钩子,然后new Watcher执行updateComponent函数。这个函数主要做的事情就是通过_render()函数把render变成虚拟dom,通过_update把虚拟dom变成真实dom插入到试图中,最后执行mount钩子函数
总结
以上大概就是我理解的new Vue干了一系列的操作,如有需要改进的地方,欢迎留言哦~~~最后来个思维导图