Vue源码之数据驱动(个人向)
#1.大致流程
# 2.具体流程
数据驱动
New VUE
Where:src/core/instance/index.js
Do:
1.使用Function实现Vue类
2.调用_init 初始化Vue
3.混入各种Mixin(暂不清晰)
Think:
各种框架无论多么如何追其本源还是由基础的JS生成的一个”类”,而后在其原型上追加方法属性等。
this._init
Where:src/core/instance/init.js
Do:
1.合并配置,(另行分析)
2.初始化⽣命周期,(另行分析)
3.初始化事件中⼼,
4.初始化渲染,
5.初始化data、props、computed、watcher…….
Think:此步功能将各种不通的功能,集中初始化,条理清楚。
$mount()
mountComponent
(实例挂载)
Where:src/platform/web/runtime/index.js
Do:调用mountComponent方法
- Where:src/core/instance/lifecycle.js
- Do:
1.调用vm._render⽅法先⽣成虚拟Node。(重点方法)
2.再 实例化 ⼀个渲染Watcher,在它的回调函数中会调⽤ updateComponent⽅法,(响应式方面)
3。最终调⽤vm._update更新DOM。(重点方法)
Think:这个实例地挂载就是调用mountComponent方法将整个渲染⼯作完成。核心两部就是下面的_render与_upadte
vm_render
(生成Vnode’虚拟node’)
Where:src/core/instance/render.js
Do:调用$createElement 生成返回Vnode
Virtual DOM 是⽤ VNode 这么⼀个 Class 去描述,它是定义在 src/core/vdom/vnode.js中的。
- Where: src/core/vdom/create-elemenet.js
-
Do:接受5个参数
1.context:表⽰VNode的上下⽂环境,它是Component类 型;
2.tag:表⽰标签,它可以是⼀个字符串,也可以是⼀个Component ;
3.data:表⽰VNode的数 据,它是⼀个 VNodeData类型,可以在flow/vnode.js 中找到它的定义;
4.children:表⽰当前VNode的⼦节点,它是任意类型的,它接下来需要被规范为标准的 VNode 数组;
5.normalizationType:表⽰⼦节点规范的类型,类型不同规范的⽅法也就不⼀样,它主要是参 考render函数是编译⽣成的还是⽤户⼿写的。-
1.children的规范化
将children变成了⼀个类型为VNode的Array如果是⼀个数组类型,
则递归调⽤ normalizeArrayChildren ; 如果是基础类型,
则通过 createTextVNode⽅法转换成 VNode 类型;
否则就已经是 VNode 类型了 -
- VNode 的创建
-
-
Think:整个过程使用上述方法再辅助Vue自己定义的Vnode类进行遍历生成Vue所需要的虚拟的node树。接下来就是渲染的操作。
vm_update
(VNode渲染成真实DOM)
Where:src/core/instance/lifecycle.js
Do:(仅讨论初次渲染)
核心方法:_path
- Where:src/platforms/web/runtime/patch.j
-
Do:使用核心方法createPatchFunction最终返回了⼀个patch方法
它接收 4个参数,
oldVnode 表⽰旧的 VNode 节点,它也可以不存在或者是 ⼀个 DOM 对象; vnode 表⽰执⾏ _render 后返回的
VNode 的节点; hydrating 表⽰是否是服 务端渲染;
removeOnly 是给 transition-group ⽤的,之后会介绍。 - 核心方法:createElm
通过虚拟节点创建真实的DOM并插⼊到它的⽗节点中
进而通过createChildren 递归调用createElm 遍历所有虚拟节点(深度优先)
接着再调⽤invokeCreateHooks⽅法执⾏所有的 create的钩⼦并把 vnode push到 insertedVnodeQueue (队列)中。
最后调用 insert⽅法把DOM插⼊到⽗节点中,也就是最基础的appendChild
先子后父 -
insert:src/core/vdom/patch.j