应该如何学习源码? 我觉得最开始有个全局观,然后切入细节的模块,带着问题去读。
vue源码学习笔记
本篇结合了阅读 https://nlrx-wjc.github.io/Learn-Vue-Source-Code/ 的笔记,感谢wjc199366(wx)的开源。
现在应该看不了了,因为发生了一些事情,大概是人民邮电出版社以影响旗下《深入浅出Vue.js》销量为由,联系微软,将电子书的仓库给关了…..
不过好在关闭之前,留了一份在本地,需要的加我微信取:tangtang1996918
阅读源码之前,建议去看看HcySunYang大佬对vue2/3中一些重要概念的解读:
http://hcysun.me/vue-design/zh/essence-of-comp.html
例如:组件传出的本质是什么?Vnode是如何设计的?Vnode是如何挂载为真实DOM的?
对阅读源码,理清思路是非常有帮助的~
源码之中没有秘密~
1.路线
变化侦测篇
学习Vue
中如何实现数据的响应式系统,从而达到数据驱动视图。
虚拟DOM篇
学习什么是虚拟DOM,以及Vue
中的DOM-Diff
原理
模板编译篇
学习Vue
内部是怎么把template
模板编译成虚拟DOM
,从而渲染出真实DOM
生命周期篇
学习Vue
中组件的生命周期实现原理
实例方法篇
学习Vue
中所有实例方法(即所有以$
开头的方法)的实现原理
全局API篇
学习Vue
中所有全局API
的实现原理
指令篇
学习Vue
中所有指令的实现原理
过滤器篇
学习Vue
中所有过滤器的实现原理
内置组件篇
学习Vue
中内置组件的实现原理
2.方法
面对繁复的源码,我们应该怎么去读? 说下适合我自己的读源码方法,抛砖引玉。
一本正经的一行行的看源码,我只能说兄弟,你他娘的真是个天才
1.一般我先扫一眼import引入的都是那些模块的js文件,一般源码的目录结构都清晰。根据引入的js文件大概都看出该js文件的依赖性,我们可以根据依赖项的多少来判断复杂程度,有个心理预期。
2.然后去看js文件主函数的输入和输出,即传参和返回都是什么,先搞清楚其主要功能。
对。不是一上来就一行行的看逻辑代码,除非你有超强的理解能力,一般是很吃力的。所以我们就先假装自己是个debug工具,先设置跳过全部函数内部细节,只观察主函数和各个内部子函数的输入和输出。(这期间肯定少不了去查看上一部引入的函数功能)。如果结合注释看了很多输入输出还是不明白其作用,那也很正常。
接下来,我们可以复制一下代码片段,做一些测试来证实部分我们对某些函数功能的猜想。有了这些,我们脑中大多都能有个框架。
其实这跟证明数学题的思路十分类似,先提出假设,然后用各种公理,定理来慢慢推导证明。
3.深入每个函数内部的细节。这个就八仙过海各显神通了。不过我觉得还可以先做减法,即根据注释解决兼容性和一些判断环境的hack先给屏蔽掉,关注每个函数主要的逻辑,等把整个模块的脉络弄清楚后,有空再去看看哪些hack。细节不清楚的同样测试,用结果去逆推过程。
4.做笔记,自己写一遍梳理清楚,把你觉得一些很精妙的思路,有趣的类比联想,方法总结,都可以记录下来
复杂的东西都是由简单的东西构成,人们擅长将东西变复杂,却不擅长将东西变简单。
3.目录结构
强烈建议浏览一遍,源码中很多都是复用的,纵观全局,再某些判断上是能够帮上忙的~
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
| src ├─ compiler │ ├─ codeframe.js │ ├─ codegen │ │ ├─ events.js │ │ └─ index.js │ ├─ create-compiler.js │ ├─ directives │ │ ├─ bind.js │ │ ├─ index.js │ │ ├─ model.js │ │ └─ on.js │ ├─ error-detector.js │ ├─ helpers.js │ ├─ index.js │ ├─ optimizer.js │ ├─ parser │ │ ├─ entity-decoder.js │ │ ├─ filter-parser.js │ │ ├─ html-parser.js │ │ ├─ index.js │ │ └─ text-parser.js │ └─ to-function.js ├─ core │ ├─ components │ │ ├─ index.js │ │ └─ keep-alive.js │ ├─ config.js │ ├─ global-api │ │ ├─ assets.js │ │ ├─ extend.js │ │ ├─ index.js │ │ ├─ mixin.js │ │ └─ use.js │ ├─ index.js │ ├─ instance │ │ ├─ events.js │ │ ├─ index.js │ │ ├─ init.js │ │ ├─ inject.js │ │ ├─ lifecycle.js │ │ ├─ proxy.js │ │ ├─ render-helpers │ │ ├─ render.js │ │ └─ state.js │ ├─ observer │ │ ├─ array.js │ │ ├─ dep.js │ │ ├─ index.js │ │ ├─ scheduler.js │ │ ├─ traverse.js │ │ └─ watcher.js │ ├─ util │ │ ├─ debug.js │ │ ├─ env.js │ │ ├─ error.js │ │ ├─ index.js │ │ ├─ lang.js │ │ ├─ next-tick.js │ │ ├─ options.js │ │ ├─ perf.js │ │ └─ props.js │ └─ vdom │ ├─ create-component.js │ ├─ create-element.js │ ├─ create-functional-component.js │ ├─ helpers │ ├─ modules │ ├─ patch.js │ └─ vnode.js ├─ platforms │ ├─ web │ │ ├─ compiler │ │ ├─ entry-compiler.js │ │ ├─ entry-runtime-with-compiler.js │ │ ├─ entry-runtime.js │ │ ├─ entry-server-basic-renderer.js │ │ ├─ entry-server-renderer.js │ │ ├─ runtime │ │ ├─ server │ │ └─ util │ └─ weex │ ├─ compiler │ ├─ entry-compiler.js │ ├─ entry-framework.js │ ├─ entry-runtime-factory.js │ ├─ runtime │ └─ util ├─ server │ ├─ bundle-renderer │ │ ├─ create-bundle-renderer.js │ │ ├─ create-bundle-runner.js │ │ └─ source-map-support.js │ ├─ create-basic-renderer.js │ ├─ create-renderer.js │ ├─ optimizing-compiler │ │ ├─ codegen.js │ │ ├─ index.js │ │ ├─ modules.js │ │ ├─ optimizer.js │ │ └─ runtime-helpers.js │ ├─ render-context.js │ ├─ render-stream.js │ ├─ render.js │ ├─ template-renderer │ │ ├─ create-async-file-mapper.js │ │ ├─ index.js │ │ ├─ parse-template.js │ │ └─ template-stream.js │ ├─ util.js │ ├─ webpack-plugin │ │ ├─ client.js │ │ ├─ server.js │ │ └─ util.js │ └─ write.js ├─ sfc │ └─ parser.js └─ shared ├─ constants.js └─ util.js
|