Vue进阶 | 虚拟DOM (二)源码浅析

175 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第4天,点击查看活动详情

Vue通过虚拟DOM操作真实DOM来进行数据的更新

image.png

当我们在一个Vue页面中声明段HTML代码,并绑定一个变量的时候,页面中展示的内容会根据myTitle数据值的变化实时更新。

<div>{{ myTitle }}<div>

那么在这个过程中发生了什么呢?我们先来看看源码文件的结构。

image.png

VNode数据结构

在源码中(/core/vdom/vnode.js)展现了关于Vnode结点的设计,包括属性/样式/事件等等

image.png

createElement 创建VNode

在源码中(/core/vdom/create-element.js),通过createElement来创建虚拟节点VNode,虚拟DOM树由无数个虚拟节点组成(也就是VNode),VNode 必须唯一。其中包括:

  • 注释节点
  • 文本节点
  • 元素节点
  • 组件节点
  • 函数式组件节点
  • 克隆节点

createElement调用_createElement(),_createElement()创建vnode对象,返回VNode:

image.png

createElement接收5个参数:

  • context  // 虚拟节点的上下文环境,类型:Component
  • tag // 标签
  • data //  虚拟节点的数据,类型:VNodeData
  • children // 示当前虚拟节点的子节点
  • normalizationType // 子节点规范的类型

VNode渲染成DOM

在生命周期中的mounted阶段,会将DOM节点进行挂载,此时的节点都是新节点,会全部渲染。

patch

/core/vdom/patch.ts 文件中,DOM-Diff进行了对新旧的虚拟节点VNode的对比,找到差异后更新到真实DOM,也就是执行diff算法,下文中会详细介绍。

完整流程

模板------->编译------>执行渲染函数----->生成虚拟节点----->createElement(将VNode渲染成DOM节点)----->patch(新旧的虚拟节点对比)----->更新视图

总结

在全局实例对象的初次编译时,Templete内的标签被编译成虚拟节点VNode,并且缓存在内存中,在数据变化时后通过新旧对 && diff算法更新DOM树,视图更新。