# vue 源码
# 版本
version 2.6.10
# src目录结构
- compiler 编译相关
- core 核心代码
- platforms 不同平台的支持 web/ hybrid
- server 服务端渲染
- sfc 解析'.vue'文件
- shared 公共的代码
# vue本质是个类/function
# 数据驱动
this.message === this._data.message
# new Vue发生了什么
- 源码位置
src/core/instance/index.js - vue 初始化主要做了
合并配置,初始化生命周期,初始化事件中心,初始化渲染,初始化data props computed watcher ... - 总结: new Vue > init > $mount > compile > render > VNode > patch > DOM
# Vue实例挂载的实现 $mount
compiler版本的
$mount源码位置src/platform/web/entry-runtime-with-compiler.js$mount方法对el参数做了限制, 不能在挂载在html,body根元素上在vue
2.x中,所有vue的组件最终都需要render方法render方法。 如果没有定义render就会把el或template字符串转成render方法转成render方法的过程是vue的一个
在线编译的过程 调用compileToFunctions原型上的$mount 在源码中
src/platform/web/runtime/index.js$mount方法支持传入2个参数,第一个el表示挂载的元素,第二个hydrating和服务端渲染有关,浏览器环境下不需要传这个参数$mount实际上调用的是
mountComponent方法. 源码位置src/core/instance/lifecycle.jsmountComponent方法的核心是 实例化一个Watcher, 在回调函数中调用updateComponent方法Watcher在这里起到了两个作用 一是初始化执行回调,二是vm实例中监听数据变化执行回调
# render
render是一个私有方法(_render), 用来把实例渲染成虚拟node. 源码位置src/core/instance/render.js- render函数中的
createElement方法 就是vm.$createElement - 在
initRender中vm._c和vm.$createElement都调用 createElement方法 vm._c方法是模版编译成render使用,vm.$createElement方法是用户手写render方法使用
# Virtual DOM
Virtual DOM就是用原生的js对象去描述一个DOM节点. vue中的VNode使用Class去描述的- 源码位置
src/core/vdom/vnode.js - VDOM 映射到真实的dom需要经历 VNode 的 create, diff,pathch 等等
# createElement
- vue 用
createElement方法创建VNode。 源码位置src/core/vdom/create-elemenet.js createElement是对_createElement方法的封装,允许调用的参数更加灵活_createElement方法有5个参数
* `context` 表示VNode的上下文环境
* `tag`表示标签 , 字符串/`Component`
* `data` 表示VNode的数据
* `children` 表示当前VNode的子节点
* `normalizationType` 表示子节点的规范类型
children的规范化
* Virtual DOM 实际上是一个树状结构, 每一个VNode 可能会有若干个子节点,
* 根据`normalizationType`值来规范 `children`, 分别是`normalizeChildren`,`simpleNormalizeChildren` 源码位置 `src/core/vdom/helpers/normalzie-children.js`
* `simpleNormalizeChildren`方法是将`children`数组打平, 让children的深度自有1层
* `normalizeChildren` 有两种应用方式。 一种是用户手写的render函数,会调用`createTextVNode`。 另一种是当编译`slot v-for`时,会调用`normalizeArrayChildren`
VNode的创建
* 规范化`children` 后就去创建VNode实例
# update
update是私有方法(_update), 调用的时机有两个,一个是首次渲染,另一个是数据更新 源码位置src/core/instance/lifecycle.js_update方法就是把VNode渲染成真实DOM- _update的核心是
vm.__patch__源码位置src/platforms/web/runtime/index.js Vue.prototype.__patch__在浏览器端 指向的是patch, 源码位置src/platforms/web/runtime/patch.jscreatePatchFunction接收两个参数modules定义了一些模块的钩子函数,nodeOps封装了一系列dom操作的方法. 最终返回了一个patch方法patch方法 接收4个参数.oldVnode表示旧的VNode节点,vnode表示执行_render后返回的VNode节点,hydrating表示是否是服务端渲染,removeOnly是给transition-group用的