应该如何学习源码? 我觉得最开始有个全局观,然后切入细节的模块,带着问题去读。

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.路线
  1. 变化侦测篇

    学习Vue中如何实现数据的响应式系统,从而达到数据驱动视图。

  2. 虚拟DOM篇

    学习什么是虚拟DOM,以及Vue中的DOM-Diff原理

  3. 模板编译篇

    学习Vue内部是怎么把template模板编译成虚拟DOM,从而渲染出真实DOM

  4. 生命周期篇

    学习Vue中组件的生命周期实现原理

  5. 实例方法篇

    学习Vue中所有实例方法(即所有以$开头的方法)的实现原理

  6. 全局API篇

    学习Vue中所有全局API的实现原理

  7. 指令篇

    学习Vue中所有指令的实现原理

  8. 过滤器篇

    学习Vue中所有过滤器的实现原理

  9. 内置组件篇

    学习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

评论