【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.mzph.cn/news/707351.shtml

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

相关文章

Spring中的ApplicationContext.publishEvent

简单理解 其实就是监听处理。比如找工作平台上&#xff0c;雇主 employer 发布自己的雇佣条件&#xff0c;目的是平台中有符合条件的求职者时&#xff0c;及时向雇主推荐。求职者发布简历&#xff0c;当平台发现某个求职者比较符合条件&#xff0c;就触发被动&#xff0c;推荐…

selenium元素等待及滚动条滚动

selenium三大等待&#xff0c;sleep&#xff08;强制&#xff09;、implicitlyWait&#xff08;隐式等待&#xff09;、WebDriverWait&#xff08;显式等待&#xff09;&#xff0c;主要记一下最后面的WebDriverWait。 WebDriverWait是三大等待中最常用也是最好用的一种等待方…

docker 容器修改端口和目录映射

一、容器修改端口映射 一般在运行容器时&#xff0c;我们都会通过参数 -p&#xff08;使用大写的-P参数则会随机选择宿主机的一个端口进行映射&#xff09;来指定宿主机和容器端口的映射&#xff0c;例如 docker run -it -d --name [container-name] -p 8088:80 [image-name]…

vue3的echarts从后端获取数据,用于绘制图表

场景需求&#xff1a;后端采用flask通过pymysql从数据库获取数据&#xff0c;并返回给前端。前端vue3利用axios获取数据并运用到echarts绘制图表。 第一步&#xff0c;vue中引入echarts 首先vue下载echarts npm install echarts 然后在main.js文件写如下代码 import {create…

东芝工控机维修东芝电脑PC机维修FA3100A

TOSHIBA东芝工控机维修电脑控制器PC机FA3100A MODEL8000 UF8A11M 日本东芝TOSHIBA IA controller维修SYU7209A 001 FXMC12/FXMC11;BV86R-T2GKR-DR7YF-8CPPY-4T3QD; CPU处理单元是可编程逻辑控制器的控制部分。它按照可编程逻辑控制器系统程序赋予的功能接收并存储从编程器键入…

基于 LVGL 使用 SquareLine Studio 快速设计 UI 界面

目录 简介注册与软件获取工程配置设计 UI导出源码板级验证更多内容 简介 SquareLine Studio 是一款专业的 UI 设计软件&#xff0c;它与 LVGL&#xff08;Light and Versatile Graphics Library&#xff0c;轻量级通用图形库&#xff09;紧密集成。LVGL 是一个轻量化的、开源的…

K8S之Deployment的介绍和使用

Deployment的理论和实操 Deployment控制器&#xff1a;概念、原理解读概述工作原理 编写Deployment资源清单文件使用案例&#xff1a;创建一个web站点Deployment管理pod&#xff1a;扩容、缩容通过deployment管理应用&#xff0c;实现扩容&#xff0c;把副本数变成3通过deploym…

135 Linux 系统编程12,linux命令重定向,dup 和dup2,fcntl实现dup和dup2 ,进程和程序概念,虚拟内存和物理内存映射关系,pcb进程块详解

一 linux 命令中重定向&#xff0c;使用>实现 通过 大于号 将前面的内容写入到某一个地方 cat main.c > b.txt //cat main 本身的意思是 显示main.c的值&#xff0c;后面加上 > b.txt 会将显示在屏幕上的字符全部写到b.txt中 例子&#xff1a;将 ls -l 的内容 通…

JavaScript最新实现城市级联操作,json格式的数据

前置知识&#xff1a; <button onclick"doSelect()">操作下拉列表</button><hr>学历&#xff1a;<select id"degree"><option value"0">--请选择学历--</option><option value"1">专科<…

配置前端项目到 github-pages

Quickstart for GitHub Pages - GitHub Docs

【Day59】代码随想录之动态规划_647回文子串_516最长回文子序列

文章目录 动态规划理论基础动规五部曲&#xff1a;出现结果不正确&#xff1a; 1. 647回文子串2. 516最长回文子序列 动态规划理论基础 动规五部曲&#xff1a; 确定dp数组 下标及dp[i] 的含义。递推公式&#xff1a;比如斐波那契数列 dp[i] dp[i-1] dp[i-2]。初始化dp数组…

AxureCloud配置文件详细介绍

AxureCloud配置文件详细介绍 原文地址&#xff1a;https://docs.axure.com/axure-cloud/business/custom-settings-json/ 通过修改 customsettings.json 可以修改AxureCloud私有部署的域名、端口、HTTPS、存储目录、是否开启插件等, 默认安装的路径为: C:\Program Files\Axure…

白介素IL-17靶点作用机制、全球在研管线与临床试验结果汇总分析

IL-17与化脓性汗腺炎疾病 化脓性汗腺炎&#xff08;Hidradenitis suppurativa&#xff0c;HS&#xff09;&#xff0c;也称为反痤疮&#xff0c;是一种慢性致残性和衰弱性炎症性疾病&#xff0c;其特征是深部疼痛的结节和脓肿、瘘管、窦道和疤痕&#xff0c;全球发病率约为1%~…

Mysql的储存引擎

储存引擎介绍 1. 文件系统 操作系统存取数据的一种机制 2. 文件系统类型 不管使用什么文件系统&#xff0c;数据内容不会变化 不同的是&#xff0c;存储空间、大小、速度 3. MySQL存储引擎 可以理解为&#xff0c;MySQL的“文件系统”&#xff0c;只不过功能更加强大 4. MySQL…

安装极狐GitLab Runner并测试使用

本文继【新版极狐安装配置详细版】之后继续 1. 添加官方极狐GitLab 仓库&#xff1a; 对于 RHEL/CentOS/Fedora&#xff1a; curl -L "https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.rpm.sh" | sudo bash2. 安装最新版本的极狐G…

Django项目使用vue打包前端页面使用教程

一、vue打包&#xff1a; 一般使用 npm run build 进行打包&#xff0c;打包完成后会生成一个dist文件夹 二、修改vue.config.js配置 vue.config..js配置里面增加&#xff1a; assetsDir: static 三、修改Django项目 将Django的static文件夹删除&#xff0c;移动di…

Flink动态分区裁剪

1 原理 1.1 静态分区裁剪与动态分区裁剪 静态分区裁剪的原理跟谓词下推是一致的&#xff0c;只是适用的是分区表&#xff0c;通过将where条件中的分区条件下推到数据源达到减少分区扫描的目的   动态分区裁剪应用于Join场景&#xff0c;这种场景下&#xff0c;分区条件在joi…

Oracle中序列

1. Sequence 定义 在Oracle中可以用SEQUENCE生成自增字段。Sequence序列是Oracle中用于生成数字序列的对象&#xff0c;可以创建一个唯一的数字作为主键。 2. 为什么要用 Sequence 你可能有疑问为什么要使用序列&#xff1f; 不能使用一个存储主键的表并每次递增吗&#xf…

milvus upsert流程源码分析

milvus版本:v2.3.2 整体架构: Upsert 的数据流向: 1.客户端sdk发出Upsert API请求。 import numpy as np from pymilvus import (connections,Collection, )num_entities, dim 4, 3print("start connecting to Milvus") connections.connect("default",…

11.题目:编号3272 小蓝的漆房

题目&#xff1a; ###本题主要考察暴力&#xff0c;枚举&#xff0c;模拟 #include<bits/stdc.h> using namespace std; const int N1e410; int a[N],b[N]; int main(){ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);int num;cin>>num;//样例个数循环for(int i…