【vue】什么是虚拟Dom,怎么实现虚拟DOM,虚拟DOM一定更快吗

什么是虚拟Dom

虚拟 DOM 基于虚拟节点 VNode,VNode 本质上是一个对象,VDOM 就是VNode 组成的

        废话,js 中所有的东西都是对象

虚拟DOM 为什么快,做了哪些优化

  1. 批量更新
    1. 多个DOM合并更新
    2. 减少浏览器的重排和重绘
  2. 局部更新
    1. 通过新VDOM对比,diff 算法
    2. 只更新需要重新渲染的真实 DOM
    3. 减少开销
  3. 跨平台支持
    1. node、浏览器、移动端、小程序都可以支持

虚拟DOM一定更快吗,不一定

  1. 额外的内存占用
    1. 虚拟DOM需要维护一个表示整个组件树的数据结构,这可能会占用额外的内存。
  2. VDOM 生成、对比,渲染都有额外的开销
  3. VDOM 适合中大型项目
  4. 简单的程序不适合VDOM,直接操作真实DOM更好
  5. 有些框架不用VDOM也很快
    1. 使用异步渲染技术
      1. requestAnimationFrame
      2. MutationObserver

实现VDOM

vue3 源码 runtime-core/src/vnode.ts 有关于 VNode 的定义

export interface VNode<HostNode = RendererNode,HostElement = RendererElement,ExtraProps = { [key: string]: any },
> {/*** @internal*/__v_isVNode: true/*** @internal*/[ReactiveFlags.SKIP]: truetype: VNodeTypesprops: (VNodeProps & ExtraProps) | nullkey: string | number | symbol | nullref: VNodeNormalizedRef | null/*** SFC only. This is assigned on vnode creation using currentScopeId* which is set alongside currentRenderingInstance.*/scopeId: string | null/*** SFC only. This is assigned to:* - Slot fragment vnodes with :slotted SFC styles.* - Component vnodes (during patch/hydration) so that its root node can*   inherit the component's slotScopeIds* @internal*/slotScopeIds: string[] | nullchildren: VNodeNormalizedChildrencomponent: ComponentInternalInstance | nulldirs: DirectiveBinding[] | nulltransition: TransitionHooks<HostElement> | null// DOMel: HostNode | nullanchor: HostNode | null // fragment anchortarget: HostElement | null // teleport targettargetAnchor: HostNode | null // teleport target anchor/*** number of elements contained in a static vnode* @internal*/staticCount: number// suspensesuspense: SuspenseBoundary | null/*** @internal*/ssContent: VNode | null/*** @internal*/ssFallback: VNode | null// optimization onlyshapeFlag: numberpatchFlag: number/*** @internal*/dynamicProps: string[] | null/*** @internal*/dynamicChildren: VNode[] | null// application root node onlyappContext: AppContext | null/*** @internal lexical scope owner instance*/ctx: ComponentInternalInstance | null/*** @internal attached by v-memo*/memo?: any[]/*** @internal __COMPAT__ only*/isCompatRoot?: true/*** @internal custom element interception hook*/ce?: (instance: ComponentInternalInstance) => void
}

使用 createVNode 创建虚拟节点  

虚拟 dom 就是虚拟 node 节点的结合,每个 Vnode 都有一个 children 属性,children 的每个元素也是一个 VNode,他们有共同的根节点,就形成了一个虚拟的树结构。

自己实现虚拟 DOM 的重点步骤

  1. 定义一个 VNode 数据结构【这个如果是用 js,没有接口类型定义,就不用在代码中直接体现】
    1. 类中有 children 属性【用来存储子节点】
    2. 有 tag 代表标签【用来存储真实 html 的标签, div, p, span 等】
    3. 有 props 节点的属性【用来存储 html 元素的各种属性,style, class 等】
  2. 定义一个创建 VNode 的函数或类【createVNode】
  3. 定义一个渲染函数,将 VDOM 转成真实节点【render】

下面是我根据上面的步骤自己实现的:

// 创建虚拟节点函数
function createVNode(tag, props, children) {// 虚拟节点必须包含的三个属性return {isVnode: true, // 用来判断是否是虚拟节点,也不可不用这个tag,props,children // 数组}
}function render(VNode) {const { tag, props, children } = VNode// 创建真实 Dom 元素const element = document.createElement(tag)// 给 dom 元素增加属性for(let key in props) {element.setAttribute(key, props[key])}for(let i =0; i < children.length; i ++) {let child = children[i]// 如果子节点还是虚拟节点,就递归调用渲染函数if (child.isVnode ) {element.appendChild(render(child))} else {// 最终的真实节点element.appendChild(document.createTextNode(child))}}return element
}const vDom = createVNode('div', {style: 'color:red'}, [createVNode('h1', { style: 'color:blue'}, ['你好']),createVNode('p', {}, ['再见'])
])const realDom = render(vDom)
console.log(realDom)

 复制上面代码到浏览器开发者工具中可以直接运行

下面 chatgpt 给的答案,使用了一个 vnode类,看起来更好一些:

// 定义虚拟DOM节点的数据结构
class VNode {constructor(tag, props, children) {this.tag = tag;this.props = props;this.children = children;}// 渲染虚拟DOM为真实DOMrender() {const element = document.createElement(this.tag);// 设置属性for (const key in this.props) {element.setAttribute(key, this.props[key]);}// 渲染子节点this.children.forEach(child => {if (child instanceof VNode) {element.appendChild(child.render());} else {element.appendChild(document.createTextNode(child));}});return element;}
}// 创建虚拟DOM
const virtualDOM = new VNode('div', { class: 'container' }, [new VNode('h1', {}, ['Hello, Virtual DOM!']),new VNode('p', {}, ['This is a paragraph.']),
]);// 将虚拟DOM渲染到页面中
const root = document.getElementById('root');
root.appendChild(virtualDOM.render());

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/496733.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

猫头虎分享已解决Bug || 依赖问题:DependencyNotFoundException: Module ‘xyz‘ was not found 问题

博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题大全》 — 面试准备的宝典&#xff01;《IDEA开发秘籍》 — 提升你的IDEA技能&#xff01;《100天精通鸿蒙》 …

MATLAB_ESP32有限脉冲响应FIR无限脉冲响应IIR滤波器

要点 ESP32闪烁LED&#xff0c;计时LEDESP32基础控制&#xff1a;温控输出串口监控&#xff0c;LCD事件计数器&#xff0c;SD卡读写&#xff0c;扫描WiFi网络&#xff0c;手机控制LED&#xff0c;经典蓝牙、数字麦克风捕捉音频、使用放大器和喇叭、播放SD卡和闪存MP3文件、立体…

pdf怎么合并在一起?

pdf怎么合并在一起&#xff1f;在日常工作和学习中&#xff0c;我们常常需要处理大量的PDF文件。有时候&#xff0c;我们可能希望将多个PDF文件合并成一个文件&#xff0c;以便于管理和分享。这时候&#xff0c;PDF文件合并工具就能派上用场了。PDF文件合并是一种将多个PDF文件…

基于YOLOv8/YOLOv7/YOLOv6/YOLOv5的活体人脸检测系统(Python+PySide6界面+训练代码)

摘要&#xff1a;本篇博客详细讲述了如何利用深度学习构建一个活体人脸检测系统&#xff0c;并且提供了完整的实现代码。该系统基于强大的YOLOv8算法&#xff0c;并进行了与前代算法YOLOv7、YOLOv6、YOLOv5的细致对比&#xff0c;展示了其在图像、视频、实时视频流和批量文件处…

Python 全栈系列227 部署chatglm3-API接口

说明 上一篇介绍了基于算力租用的方式部署chatglm3, 见文章&#xff1b;本篇接着看如何使用API方式进行使用。 内容 1 官方接口 详情可见接口调用文档 调用有两种方式&#xff0c;SDK包和Http。一般来说&#xff0c;用SDK会省事一些。 以下是Python SDK包的git项目地址 安…

从新手到专家:AutoCAD 完全指南

&#x1f482; 个人网站:【 海拥】【神级代码资源网站】【办公神器】&#x1f91f; 基于Web端打造的&#xff1a;&#x1f449;轻量化工具创作平台&#x1f485; 想寻找共同学习交流的小伙伴&#xff0c;请点击【全栈技术交流群】 引言 AutoCAD是一款广泛用于工程设计和绘图的…

R语言——条形图数据可视化的多种方式

本文章将会介绍如何使用R语言中的ggplot2包使用条形图进行数据可视化。将会使用一个“生产企业原材料的订购与运输”的订单数据&#xff0c;该数据来自2021数学建模国赛C题。 某建筑和装饰板材的生产企业所用原材料主要是木质纤维和其他植物素纤维材料总体可分为 A B C 三种类…

Cyber RT 参数

以共享的方式实现不同节点之间数据交互的通信模式。 参数服务器是基于服务实现的&#xff0c;包含客户端和服务器端&#xff0c;服务端节点可以存储数据&#xff0c;客户端节点可以访问服务端节点操作数据&#xff0c;这个过程虽然基于请求响应的&#xff0c;但是无需自己实现…

2024年阿里云优惠券领取及使用教程_无门槛优惠券

阿里云优惠代金券领取入口&#xff0c;阿里云服务器优惠代金券、域名代金券&#xff0c;在领券中心可以领取当前最新可用的满减代金券&#xff0c;阿里云百科aliyunbaike.com分享阿里云服务器代金券、领券中心、域名代金券领取、代金券查询及使用方法&#xff1a; 阿里云优惠券…

亚信安慧AntDB助力全链路实时化

实时数据平台&#xff0c;快速实现企业全链路实时化 引入数据仓库、数据挖掘、HTAP等先进理念&#xff0c;通过实时数据应用平台来装载庞大的信息量&#xff0c;进行实时分析处理&#xff0c;克服数据处理过程中的困难&#xff0c;是当下各企事业单位、互联网、金融&#xff0c…

嵌入式学习 Day 26

数组指针和指针数组 &#xff08;题外话&#xff09; 数组指针&#xff1a;数组指针是一种指针&#xff0c;它指向一个数组的首地址。在C语言中&#xff0c;数组名本身就是一个指向数组首地址的指针&#xff0c;因此数组名可以被赋值给指针变量&#xff0c…

LeetCode59. 螺旋矩阵 II(C++)

LeetCode59. 螺旋矩阵 II 题目链接代码 题目链接 https://leetcode.cn/problems/spiral-matrix-ii/ 代码 class Solution { public:vector<vector<int>> generateMatrix(int n) {vector<vector<int>> res(n, vector<int>(n, 0));int startx …