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、拓展
 2、判断用户渲染方式的写法:  先判断render,再判断template,最后判el元素,所以反应了render优先级最高。 3、如果有模板,就编译它,最终目标是render   接着我们根据Vue的引入找到src/platforms/web/runtime文件。 src/platforms/web/runtime文件做的事情包括: 1、安装平台特有补丁函数:做初始化和更新的。 2、实现](https://math.jianshu.com/math?formula=mount%3A%20!%5BWeChat584bf4a3e2f31cac1b5163a8b6c847a4.png%5D(https%3A%2F%2Fupload-images.jianshu.io%2Fupload_images%2F21883160-d12a83611b3b49e2.png%3FimageMogr2%2Fauto-orient%2Fstrip%257CimageView2%2F2%2Fw%2F1240)%202%E3%80%81%E5%88%A4%E6%96%AD%E7%94%A8%E6%88%B7%E6%B8%B2%E6%9F%93%E6%96%B9%E5%BC%8F%E7%9A%84%E5%86%99%E6%B3%95%EF%BC%9A%20!%5BWeChat35e6c9183faf61c7561e8a671605eb14.png%5D(https%3A%2F%2Fupload-images.jianshu.io%2Fupload_images%2F21883160-2e356bbd1fafa64f.png%3FimageMogr2%2Fauto-orient%2Fstrip%257CimageView2%2F2%2Fw%2F1240)%20%E5%85%88%E5%88%A4%E6%96%ADrender%2C%E5%86%8D%E5%88%A4%E6%96%ADtemplate%EF%BC%8C%E6%9C%80%E5%90%8E%E5%88%A4el%E5%85%83%E7%B4%A0%EF%BC%8C%E6%89%80%E4%BB%A5%E5%8F%8D%E5%BA%94%E4%BA%86render%E4%BC%98%E5%85%88%E7%BA%A7%E6%9C%80%E9%AB%98%E3%80%82%203%E3%80%81%E5%A6%82%E6%9E%9C%E6%9C%89%E6%A8%A1%E6%9D%BF%EF%BC%8C%E5%B0%B1%E7%BC%96%E8%AF%91%E5%AE%83%EF%BC%8C%E6%9C%80%E7%BB%88%E7%9B%AE%E6%A0%87%E6%98%AFrender%20!%5BWeChat4e577821894bcfe6f6327f2d836040b2.png%5D(https%3A%2F%2Fupload-images.jianshu.io%2Fupload_images%2F21883160-b1d34fc9b600c085.png%3FimageMogr2%2Fauto-orient%2Fstrip%257CimageView2%2F2%2Fw%2F1240)%20!%5BWeChat9dcc4aa946d5f1a9dc0121d786934400.png%5D(https%3A%2F%2Fupload-images.jianshu.io%2Fupload_images%2F21883160-3ed115f8364f5b9b.png%3FimageMogr2%2Fauto-orient%2Fstrip%257CimageView2%2F2%2Fw%2F1240)%20%E6%8E%A5%E7%9D%80%E6%88%91%E4%BB%AC%E6%A0%B9%E6%8D%AEVue%E7%9A%84%E5%BC%95%E5%85%A5%E6%89%BE%E5%88%B0src%2Fplatforms%2Fweb%2Fruntime%E6%96%87%E4%BB%B6%E3%80%82%20src%2Fplatforms%2Fweb%2Fruntime%E6%96%87%E4%BB%B6%E5%81%9A%E7%9A%84%E4%BA%8B%E6%83%85%E5%8C%85%E6%8B%AC%EF%BC%9A%201%E3%80%81%E5%AE%89%E8%A3%85%E5%B9%B3%E5%8F%B0%E7%89%B9%E6%9C%89%E8%A1%A5%E4%B8%81%E5%87%BD%E6%95%B0%EF%BC%9A%E5%81%9A%E5%88%9D%E5%A7%8B%E5%8C%96%E5%92%8C%E6%9B%B4%E6%96%B0%E7%9A%84%E3%80%82%202%E3%80%81%E5%AE%9E%E7%8E%B0)
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