Vue3渲染机制

  1. Vue如何将模板 =》 转换为实际的DOM节点?
  2. Vue如何高效更新这些DOM节点??

虚拟DOM => Vue渲染系统的根基

虚拟DOM(VDOM) =》 编程概念:将内存中的虚拟DOM和真实节点同步

// 运行时渲染器 =》 遍历虚拟DOM树 =》 构建真实DOM树 ===》 mount
const vnode = { // 代表元素的纯JS对象
  type: 'div',
  props: {
    id: 'hello'
  },
  children: [
    // more vnodes
  ]
}

“diffing Or reconciliation” PATH过程: 内存中存在两份虚拟DOM的副本,渲染器可以遍历并比较这两颗树,找出差异,并将这些更改应用到真实DOM

虚拟DOM(VDOM)的好处:开发人员只需要关注数据展示和数据的处理逻辑,将直接的DOM操作交给渲染器完成。

渲染管道

Vue挂载流程:

  1. 编译:Vue模板被编译为渲染函数:返回虚拟DOM树的函数。
  2. Mount: 运行时渲染器调用 =》 渲染函数,遍历返回的虚拟DOM树,基于该过程构建实际的DOM节点(该阶段会追踪所有使用过的响应依赖项
  3. Patch: 当挂载期间使用的依赖项发生变化是,效果将重新运行,将创建一个新的、更新的虚拟DOM树。运行时渲染器将遍历新的VDOM树和旧的VDOM树进行比较,将必要的更新应用到实际的DOM上

模板和渲染函数

Vue模板 ====》编译成 ===》虚拟DOM渲染函数

Vue为什么推荐使用模板而不是像React中使用JSX
  1. 模板更加接近HTML,便于开发人员理解和维护
  2. 模板语法更具确定性,容易进行静态分析,Vue模板编译器可应用许多编译时优化来提供虚拟DOM性能

React VDOM VS Vue VDOM

React中的虚拟DOM是纯运行时的,调和算法必须对传入的虚拟DOM完全遍历
Vue中的虚拟DOM是同时控制编译器和运行时
编译器可以静态分析模板并在生成的代码中留下静态标记,便于提高运行时的渲染效率

🚨Vue模板编译器为提高虚拟DOM的运行时性能做出的几个主要优化:

☘️静态提升

<div>
  <div>foo</div> <!-- hoisted -->
  <div>bar</div> <!-- hoisted -->
  <div>{{ dynamic }}</div>
</div>

对于不包含任何动态绑定的静态节点,每次重新渲染时无需重新创建对应VNode并对其进行Diff处理
对于大量连续的静态VNode会被压缩成单个静态VNode,静态VNode会通过innerHTML直接挂载

☘️补丁标志(Path Flags)

<!-- class binding only -->
<div :class="{ active }"></div>

<!-- id and value bindings only -->
<input :id="id" :value="value">

<!-- text children only -->
<div>{{ dynamic }}</div>

createElementVNode("div", {
  class: _normalizeClass({ active: _ctx.active })
}, null, 2 /* CLASS */)

// 运行时渲染器可以使用按位运算检查标志,以确定是否需要执行某些工作
// 最后一个参数2是补丁标志。一个元素可以有多个补丁标志,这些标志将合并为一个数字。然后,运行时渲染器可以使 // 用按位运算检查标志,以确定是否需要执行某些工作:

☘️树扁平化

当此组件需要重新渲染时,它只需要遍历扁平化的树,而不需要遍历整个树。这称为树扁平化,它大大减少了虚拟 DOM 协调期间需要遍历的节点数。模板的任何静态部分都会被有效跳过。

渲染函数和JSX

基本用法

创建VNode

import { h } from 'vue'
const vnode = h(
  'div', // type
  {id: 'foo', class: 'bar'}, // props
  [
    // children
  ]
)

h()是hyperscript的缩写即生成HTML的JavaScript

h()函数实际上就是createVNode(),用来创建虚拟DOM

posted @ 2024-12-14 18:32  Felix_Openmind  阅读(108)  评论(0)    收藏  举报
*{cursor: url(https://files-cdn.cnblogs.com/files/morango/fish-cursor.ico),auto;}