vue2源码解析入门 (vue 2.6.14) (一)
Vue 的初始化过程:
1.执行编译,生成 render
函数。
2.一系列的初始化,数据响应式化,触发对应的生命周期钩子。
3.执行挂载的逻辑,先生成虚拟 DOM,再生成真实 DOM,更新的逻辑也是这样,只不过多出了对比虚拟 DOM 的一个步骤。
一、我们到 vue仓库 下载 Vue2.6.14 的源码。
https://github.com/vuejs/
先来看一下整体目录结构
二、首先通过 package.json
中的打包命令,我们可以找到完整版的 Vue 的入口文件。
在该文件中,看到vue用的是的rollup编辑的
rollup -w - c
--wacth | -w 开启文件监视 // 它检测到磁盘上单个模块已经改变,它会重新构建你的文件束
--config | -c 指定配置文件地址
(1)package.json
(2)scripts/config.js
找到config.js文件,路径为scripts/config.js
需要拿到 --environment传入的环境变量,根据配置TARGET的配置选择 web-full-dev的配置
找到resole的封装找到对应的路径配置alias.js
(3)scripts/alias.js
(4)src/platforms/web/entry-runtime-with-compiler.js
所以我们先来到 src/platforms/web/entry-runtime-with-compiler.js
文件
通过一层一层的分析,终于快要到vue的核心代码了
简单来看下,这个文件主要是扩展了 Vue.prototype.$mount
方法
根据源码,我们还可以得到一个小知识,就是如果 Vue 的 options 中同时传入 el, render, template,哪个优先级最高?
通过下面这段代码,我们可以发现,render
的优先级是最高的,因为如果是 render
,则直接走到最下面的 mount
了,其次是 template
,然后再是 el
。
在src/platforms/web/entry-runtime-with-compiler.js
这个文件中看到引入的vue
也就是这个文件src/platforms/web/runtime/index.js
文件
(5)src/platforms/web/runtime/index.js
这里有 2 个比较重要的方法
可以看到,原始的 $mount
是在这里被赋值的,不过我们还没找到初始的 Vue
类,所以我们继续进入 src/core/index.js
(6) src/core/index.js
initGlobalAPI
定义了一些全局 API,比如 set
,use
之类的,我们继续看 instance/index
中的代码。
三、原始的 Vue
(7) src/core/instance/index.js
在这里,终于找到原始的 Vue
了
构造函数定义了一个Vue
new Vue
的入口就是这里。
它调用了 _init
方法,而 _init
方法是 initMixin
混入进来的。
找到initMixin
(8) src/core/instance/init.js
在这里,可以看到Vue 的初始化过程
看一下源码中的 initState
(9)src/core/instance/state.js
可以看到数据响应式的做法,初始化处理 data
的函数 initData()
这个 initData方法调用了proxy
和 observe
(10)src/core/observer/index.js
来看看observe
在构造函数中,发现每个被处理过的对象,都会挂上 _ob_
这个 key
,代表着 Observer
实例,
另外 this.dep = new Dep()
这个代码要关注下,即每个 Observer
有一个独有的 dep
依赖。
(11) src/core/instance/lifecycle.js
Watcher
每个组件只有一个 Watcher
,当然用户也可能通过 watch
创建额外的。这里我们也可以看到组件的挂载过程,先调用 render
函数,那 render
生成虚拟 DOM,然后交给 _update
函数。
看下 _update
函数的逻辑,可以看到就是使用 _patch_
来对比前后虚拟 DOM,然后生成真实 DOM,再进行渲染,patch
也就是我们常说的 diff
。
(12) src/core/observer/watcher.js
从构造函数中可以发现 this.get
方法的调用,pushTarget
用来设置 Dep.target
,this.getter
则是调用了传进来的更新函数