vue3从精通到入门2:虚拟DOM的生成与真实DOM的转化

虚拟 DOM 实现是 Vue 框架的核心部分之一,它负责在真实 DOM 之上抽象出一个轻量级的、可复用的 JavaScript 对象树,用于高效地更新视图。

什么是虚拟DOM?

虚拟 DOM 是一个编程概念,它将真实的 DOM 树抽象为一个轻量级的 JavaScript 对象树。当应用状态发生变化时,Vue 会先比较新的虚拟 DOM 树和旧的虚拟 DOM 树之间的差异,然后只更新这些差异部分对应的真实 DOM,而不是重新渲染整个页面。这种方式大大提高了渲染性能。

而我们如何将虚拟DOM转化成真实DOM呢?

App.vue:

html 复制代码
<template>
  <div>
    <a href="https://vitejs.dev" target="_blank">
      <img src="/vite.svg" class="logo" alt="Vite logo" />
    </a>
    <a href="https://vuejs.org/" target="_blank">
      <img src="./assets/vue.svg" class="logo vue" alt="Vue logo" />
    </a>
  </div>
  <HelloWorld msg="Vite + Vue" />
</template>

从我们编写的vue代码以及转换成真实DOM整个流程如下:

模板 > render函数 > 虚拟DOM > 真实DOM

上图中是我写的App.vue。我们将其打印出来

javascript 复制代码
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'

console.log(App); // 打印出来的模板

createApp(App).mount('#app')

打印结果:

我们可以看到这个render函数,我们的虚拟DOM是由render函数创建的。

javascript 复制代码
export function render(_ctx, _cache, $props, $setup, $data, $options) {
  const _component_HelloWorld = _resolveComponent("HelloWorld")

  return (_openBlock(), _createElementBlock("template", null, [
    _createElementVNode("div", null, [
      _createElementVNode("a", {
        href: "https://vitejs.dev",
        target: "_blank"
      }, [
        _createElementVNode("img", {
          src: "/vite.svg",
          class: "logo",
          alt: "Vite logo"
        })
      ]),
      _createElementVNode("a", {
        href: "https://vuejs.org/",
        target: "_blank"
      }, [
        _createElementVNode("img", {
          src: "./assets/vue.svg",
          class: "logo vue",
          alt: "Vue logo"
        })
      ])
    ]),
    _createVNode(_component_HelloWorld, { msg: "Vite + Vue" })
  ]))
}

当我的虚拟DOM创建出来后,如何转成真实DOM呢?

这里用到了patch 函数:

patch是 Vue 中用于比较和更新虚拟 DOM 的核心函数。它接受两个参数:旧的 VNode 和新的 VNode。根据这两个节点的类型和属性等信息,patch 函数会决定是否需要更新真实 DOM,以及如何更新。

简单表示下patch相关作用!

javascript 复制代码
function patch(  
  n1: VNode | null,  // 旧虚拟DOM
  n2: VNode,  // 新的虚拟DOM
  container: HostNode,  
  anchor: ?HostNode = null,  
  parentComponent: ?Component = null,  
  parentSuspense: ?SuspenseBoundary = null,  
  isSVG: boolean = false,  
  optimized: boolean = false  
): VNode {  
  // ...  
  const { type, ref, shapeFlag } = n2;  
  
  switch (type) {  
    case Text:  
      // 处理文本节点  
      // ...  
      break;  
    case Comment:  
      // 处理注释节点  
      // ...  
      break;  
    case Static:  
      // 处理静态节点  
      // ...  
      break;  
    case Fragment:  
      // 处理 Fragment 节点  
      // ...  
      break;  
    default:  
      // 处理元素或组件节点  
      if (shapeFlag & ShapeFlags.ELEMENT) {  
        // ... 处理元素节点 ...  
      } else if (shapeFlag & ShapeFlags.COMPONENT) {  
        // ... 处理组件节点 ...  
      }  
      // ...  
  }  
  
  // ... 其他逻辑,如处理子节点、引用、挂载等 ...  
}

后面单开一章讲解patch!

相关推荐
前端 贾公子1 分钟前
Milvus使用指南 (下)
java·服务器·前端
用户542778485154015 分钟前
浏览器后台休眠节流
前端
蜡台15 分钟前
Vue 3 原生 ESM 开发实战:不用打包工具,从零搭建组件化应用
前端·javascript·vue.js·html
我的div丢了肿么办19 分钟前
grid布局justify-items和align-items、justify-content和align-content
前端·css
用户2986985301419 分钟前
在 React 中使用 JavaScript 将 HTML 转换为图片
javascript·react.js·html
寻缘千鹤21 分钟前
LogicFlow流程图 PNG 导出「线上按钮置灰、无反应」故障复盘
前端·javascript·vue.js
梨想橙汁25 分钟前
Vite 优化、踩坑汇总 + Webpack 迁移 Vite 实战
前端·webpack·vite
10share28 分钟前
给 JSX 组件也来一份 Vue 式 scoped:jsx-scoped 让样式隔离不再靠自觉
前端·vue.js
小聪70828 分钟前
elpis-core 领域模型驱动设计解析
前端
北城笑笑29 分钟前
Vue 104 ,AI + ECharts + Word:大模型数据可视化报告生成实战(前端导出图文并茂 Word 文档)
前端·vue.js·word·echarts