vue项目地址:https://github.com/vuejs/vue
当前版本号:2.6.11
一、vue初始化
1、基本目录结构:

WeChat640327ff8c41378361241abdd4c63a5a.png
核心代码目录结构:

WeChatc5510a06b4d2d69b49f0c5345cfd4d1a.png
2、安装依赖以及添加配置
安装依赖: npm i
安装phantom.js时即可终止
安装rollup: npm i -g rollup
修改dev脚本,添加sourcemap,package.json
"dev": "rollup -w -c scripts/config.js --sourcemap --environment TARGET:web- full-dev",
运行开发命令: npm run dev,(加上sourcemap是为了能产生映射文件,能浏览器中进行断点调试)
命令跑起来之后,即可以关闭命令,找到dist目录下会发现vue.js和vue.js.map(映射文件)
在examples/test目录下创建01.init.html
引入前面创建的vue.js,samples/commits/index.html
<script src="../../dist/vue.js"></script>
3、源码初始化分析:
找到package.json文件,找到script对象,可以看到不同的打包方式。

WeChatc37173f866515317285698cee5fcb618.png
rollup打包前端js项目用的比较多,webpack打包前端app项目用的比较多。

WeChatca0f7d986567415488ce0b380dd5f78c.png
提示:平时我们用vue-cli的vue版本是是运行时版本,不带编译器。意味着我们我在new vue里不能使用template模板。使用会报错,只能使用render进行渲染。而html里的new Vue所使用的版本是包含编译器的,所以可以再js中使template模板。

WeChat2bce9ce62383d4baeca9ba1960e8c769.png
根据文件代码提示找到config.js文件
dev脚本中 -c scripts/config.js 指明配置文件所在
参数 TARGET:web-full-dev 指明输出文件配置项,line:123

WeChatad97064230075a8003175864c077ff40.png
使用command+鼠标点击resolve,可以看到aliases数组,然后点击aliases,就可以看到vue路径

WeChate53a1aa5546cdec89b3b9cc8443b4fc0.png

WeChat54fa32ebf30317801a72a9b72ccc1cdc.png
至此,我们知道了vue入口文件。
entry-runtime-with-compiler.js做了什么事:
1、拓展
mount: 初始化挂载
WeChat3ae79f6aa2516f5d73fc7d8e2c59d9be.png
接着我们继续找到vue的引入文件的地方:
src/core/index.js做的事情包括:
1、初始化全局api:包括Vue.use等api。

WeChataca872e0bd6b69156f9717cedd6e8f12.png
继续寻根找到Vue:
找到src/core/instance/index.js文件,至此就能看到Vue的构造方法。

WeChat745c38eb04e36e97cf03a83999954bec.png
1、Vue的构造函数主要是进行了初始化。
那么 new Vue的时候都做了什么初始化。

WeChata221c90f248ce1ab1b8a545203794e1d.png

WeChatb6def94e931b1ce2db3037d32e026442.png

WeChat3269d792afafeea184c8f7db92679307.png
二、响应式
1、找到initState()函数,这是初始化响应式的入口。

WeChat85e2b5c544266f5d441aa121d3f19712.png
2、initstate()函数做了三件事:如下图。

WeChat1ec4cb479fe6855582395fa1d39b6935.png
3、进入initData()函数。

WeChat6b9134bfb3cdaa532a436432f863433d.png
第一步检查是否有命名冲突,第二步,进行递归响应式处理。
4、进入到observe函数。

WeChat576155b1027e8425ef798ed8e5f4cb21.png
第一步获取ob实例,如果没有则进行响应式的添加。
5、进入到Observer类,进行obj和array的区分。

WeChataa17b7b16d11f9a64b166017b2fef271.png
obj 的响应式
6、我们先看obj,进入到walk函数中。

WeChate98f54534657350ef6aa026e4c8e66af.png
对对象的key进行遍历,进入到deineReactive会发现重要的函数Object.defineProperty()。
7、进入defineReactive函数

WeChat7d3dbd76cab1f89a529c5ca461ede3f7.png
按照正常的方式,是一个组件一个watcher,但是如果用户手动添加了watcher,则dep和watcher是多对多的关系,则dep和whatcher进行相互依赖的相互添加。这样才能实现通知更新。
8、点击进入到dep.depend()可以查看到在相互添加引用。

WeChat9fc7b38ec9bbcf1a0c642151f3da19d7.png
array的响应式:
array的响应的核心思想就是将七个会改变原始数组的方法进行覆盖。
找到src/core/observe/array.js文件,做的事情入下图备注:

WeChatd8dd4cab82788b37048ead4595db9e68.png

WeChat8cc60c53d096c70e45441b6fc8a731c1.png
最后覆盖是分ie浏览器和其他浏览器,ie浏览器需要遍历进行覆盖。

image.png