当前位置: 首页 > news >正文

初识虚拟DOM渲染器

初识虚拟DOM渲染器

    • 什么是虚拟DOM
    • 什么是渲染器
    • 渲染器的实现
    • 组件是什么

什么是虚拟DOM

首先简单说一下什么是虚拟DOM,虚拟DOM就是一个描述真实DOM的JS对象
例如:

真实的DOM元素

<div onClick="alert('click me')">click me</div>

可以用下面的JS对象(虚拟DOM)描述,再通过渲染器渲染成真实的DOM

// 描述虚拟DOM对象
const vnode = {tag: "div",props: {onClick: () => {alert("click, me")}},children: "click me"
}

什么是渲染器

渲染器的作用就是把虚拟DOM渲染成真实的DOM,如下图所示:
渲染器

渲染器的实现

详细看代码描述:

重点看 mountElement 函数部分,描述如何通过js对象渲染出真实的DOM元素

/** File Created: Monday, 6th March 2023 6:34:24 pm* Author: hotsuitor (hotsuitor@qq.com)* -----* Last Modified: Monday, 6th March 2023 6:34:50 pm* Modified By: hotsuitor (hotsuitor@qq.com>)* -----* Copyright 2022 - 2023 Your Company, Your Company*//*** 渲染器* @param {*} vnode 虚拟DOM对象* @param {*} container 真实的DOM元素,作为挂载点,* 渲染器会把虚拟DOM渲染到该挂载点下*/
function renderer(vnode, container) {if (vnode.tag === 'string') {// 说明描述的是标签元素mountElement(vnode, container)}
}/*** 渲染标签元素* @param {*} vnode* @param {*} container*/
function mountElement(vnode, container) {// 使用vnode.tag作为标签名创建DOM元素const el = document.createElement(vnode.tag)// 遍历 vnode.props ,将属性、事件添加到DOM元素for (const key in vnode.props) {// on开头表示是事件if (/^on/.test(key)) {// 添加事件,onClick->click, 事件注册el.addEventListener(key.substring(2).toLowerCase(), vnode.props[key])}}// 递归处理 childrenif (typeof vnode.children === 'string') {// 是字符串,说明是文本节点,直接添加到父元素el.appendChild(document.createTextNode(vnode.children))} else if (Array.isArray(vnode.children)) {// 遍历处理children子节点vnode.children.forEach((child) => renderer(child, el))}// 将元素添加到挂在点下container.appendChild(el)
}// demo
const vnode = {tag: 'div',props: {onClick: () => {alert('click me!')},},children: 'click me',
}renderer(vnode, document.body)

组件是什么

现在项目开发基本离不开组件的封装,我们再看一下组件是什么?

组件的本质是一组DOM元素的封装,组件是由一组虚拟DOM元素组成的内容。目的是使代码可复用性提高,不必写冗余代码

下面看代码实现,重点看 mountComponent 函数部分,组件是一个封装了一组虚拟DOM的对象。通过复用这个对象的虚拟DOM,就可以实现了组件的复用。

/** File Created: Monday, 6th March 2023 6:34:24 pm* Author: hotsuitor (hotsuitor@qq.com)* -----* Last Modified: Monday, 6th March 2023 6:34:50 pm* Modified By: hotsuitor (hotsuitor@qq.com>)* -----* Copyright 2022 - 2023 Your Company, Your Company*//*** 渲染器* @param {*} vnode 虚拟DOM对象* @param {*} container 真实的DOM元素,作为挂载点,* 渲染器会把虚拟DOM渲染到该挂载点下*/
function renderer(vnode, container) {if (vnode.tag === 'string') {// 说明描述的是标签元素mountElement(vnode, container)} else if (vnode.tag === 'object') {// 描述的是组件mountComponent(vnode, container)}
}/*** 渲染标签元素* @param {*} vnode* @param {*} container*/
function mountElement(vnode, container) {// 使用vnode.tag作为标签名创建DOM元素const el = document.createElement(vnode.tag)// 遍历 vnode.props ,将属性、事件添加到DOM元素for (const key in vnode.props) {// on开头表示是事件if (/^on/.test(key)) {// 添加事件,onClick->click, 事件注册el.addEventListener(key.substring(2).toLowerCase(), vnode.props[key])}}// 递归处理 childrenif (typeof vnode.children === 'string') {// 是字符串,说明是文本节点,直接添加到父元素el.appendChild(document.createTextNode(vnode.children))} else if (Array.isArray(vnode.children)) {// 遍历处理children子节点vnode.children.forEach((child) => renderer(child, el))}// 将元素添加到挂在点下container.appendChild(el)
}/*** 渲染组件* @param {*} vnode* @param {*} container*/
function mountComponent(vnode, container) {// tag是组件对象,调用render方法得到渲染的内容(虚拟DOM)const subtree = vnode.tag.render()renderer(subtree, container)
}/** 组件虚拟DOM */
const MyConpoment = {render() {return {tag: 'div',props: {onClick: () => {alert('hello')}},children: 'click me component'}}
}const vnode = {tag: MyConpoment
}renderer(vnode, document.body)

相关文章:

初识虚拟DOM渲染器

初识虚拟DOM渲染器什么是虚拟DOM什么是渲染器渲染器的实现组件是什么什么是虚拟DOM 首先简单说一下什么是虚拟DOM&#xff0c;虚拟DOM就是一个描述真实DOM的JS对象 例如&#xff1a; 真实的DOM元素 <div onClick"alert(click me)">click me</div>可以…...

工作日志day03

同时构建静态和动态库 //如果用这种方式&#xff0c;只会构建一个动态库&#xff0c;虽然静态库的后缀是.a ADD_LIBRARY(hello SHARED ${LIBHELLO_SRC}) ADD_LIBRARY(hello STATIC ${LIBHELLO_SRC}) //修改静态库的名字&#xff0c;这样是可以的&#xff0c;但是我们往往希望他…...

【数据挖掘与商务智能分析】第三章 线性回归模型

一元线性回归 一元线性回归的代码实现 1. 绘制散点图 import matplotlib.pyplot as plt X = [[1], [2], [4], [5]] Y...

iOS开发之UIStackView基本运用

UIStackView UIStackView是基于自动布局AutoLayout&#xff0c;创建可以动态适应设备方向、屏幕尺寸和可用空间的任何变化的用户界面。UIStackView管理其ArrangedSubview属性中所有视图的布局。这些视图根据它们在数组中的顺序沿堆栈视图的轴排列。由axis, distribution, align…...

【java】为什么 main 方法是 public static void ?

main 方法是我们学习Java编程语言时知道的第一个方法&#xff0c;你是否曾经想过为什么 main 方法是 public、static、void 的。当然&#xff0c;很多人首先学的是C和C&#xff0c;但是在Java中main方法与前者有些细微的不同&#xff0c;它不会返回任何值&#xff0c;为什么 ma…...

最简单的线性回归模型-标量

首先考虑yyy为标量&#xff0c;www为标量的情况&#xff0c;那么我们的线性函数为ywxbywxbywxb。每批输入的量batch size 为111&#xff0c;每批输入的xxx为一个标量&#xff0c;设为x∗x^*x∗&#xff0c;标签yyy同样为一个标量&#xff0c;设为y∗y^*y∗。因此每批训练的损失…...

k8s-Kubernetes集群升级

文章目录前言一、集群升级1.部署cri-docker &#xff08;所有集群节点&#xff09;2.升级master节点3.升级worker节点前言 一、集群升级 https://v1-24.docs.kubernetes.io/zh-cn/docs/tasks/administer-cluster/kubeadm/kubeadm-upgrade/ 1.部署cri-docker &#xff08;所有…...

Linux25 -- 监听队列链接上限测试、命令uname、ulimit

一、监听队列链接上限测试 1、res listen(sockfd,5); //创建监听队列res listen(sockfd,5);不懂版本有不同的限制&#xff0c;2.6早期版本有限制为128&#xff0c;超过默认为128&#xff0c;可使用uname -a 查看版本 2、测试将链接数到达上限&#xff0c; 方法&#xff1…...

idea:地址被占用

问题启动idea报&#xff1a;java.net.BindException: Address already in use: bind&#xff0c;具体截图如下&#xff1a;解决步骤1、首先想到的是改idea端口&#xff0c;但按网上方法试下了几个4位数和5位数的端口&#xff0c;没啥作用2、根据idea抛异常的弹出框提示&#xf…...

JavaScript常用小技巧(js优化)

JavaScript常用小技巧&#xff08;js优化&#xff09;常见JS操作1、解构交换两数2、短路赋值3、if 判断优化4、 switch 判断优化6、动态正则匹配Number1、幂运算2、安全计算String1、反转字符串、判断是否回文数2、数组求和3、初始化二维数组Object1、对象遍历2、冻结对象3、解…...

【项目实战】MySQL 5.7中的关键字与保留字详解

一、什么是关键字和保留字 关键字是指在SQL中有意义的字。 某些关键字&#xff08;例如SELECT&#xff0c;DELETE或BIGINT&#xff09;是保留的&#xff0c;需要特殊处理才能用作表和列名称等标识符。 这一点对于内置函数的名称也适用。 二、如何使用关键字和保留字 非保留关…...

Git图解-常用命令操作

目录 一、前言 二、初始化仓库 三、添加文件 四、Git 流程全景图 五、Git工作流程 六、工作区和暂存区 七、查看文件状态 八、查看提交日志 九、查看差异 十、版本回退 十一、管理修改 十二、修改撤销 十三、删除文件 十四、分支管理 十五、项目分支操作 十六、…...

LeetCode096不同的二叉搜索树(相关话题:卡特兰数)

目录 题目描述 解题思路 代码实现 进出栈序列理解卡特兰数分析策略 相关知识 参考文章 题目描述 给你一个整数 n &#xff0c;求恰由 n 个节点组成且节点值从 1 到 n 互不相同的 二叉搜索树 有多少种&#xff1f;返回满足题意的二叉搜索树的种数。 示例 1&#xff1a; …...

软件测试7

一 CS和BS软件架构 CS&#xff1a;客户端-服务器端&#xff0c;BS&#xff1a;浏览器端-服务器端 区别总结&#xff1a; 1.效率&#xff1a;c/s效率高&#xff0c;某些内容已经安装在系统中了&#xff0c;b/s每次都要加载最新的数据 2.升级&#xff1a;b/s无缝升级&#xff0c…...

12 结构:如何系统设计框架的整体目录?

到现在&#xff0c;我们已经将 Gin 集成到框架 hade 中&#xff0c;同时又引入了服务容器和服务提供者&#xff0c;明确框架的核心思想是面向服务编程&#xff0c;一切皆服务&#xff0c;所有服务都是基于协议。后续也会以服务的形式&#xff0c;封装一个个的服务&#xff0c;让…...

假如你知道这样的MySQL性能优化

1. 为查询缓存优化你的查询 大多数的 MySQL 服务器都开启了查询缓存。这是提高性最有效的方法之 一&#xff0c;而且这是被 MySQL 的数据库引擎处理的。当有很多相同的查询被执行了多次的时候&#xff0c;这些查询结果会被放到一个缓存中&#xff0c;这样&#xff0c;后续的相同…...

79、ClimateNeRF: Physically-based Neural Rendering for Extreme Climate Synthesis

简介主页物理模拟可以很好地预测天气影响。神经辐射场产生SOTA场景模型。ClimateNeRF 允许我们渲染真实的天气效果&#xff0c;包括雾霾、雪和洪水 &#xff0c;结果可以通过有物理意义的变量来控制&#xff0c;比如水位 &#xff0c;这允许人们可视化气候变化的结果将对他们产…...

前端面试题(一)

目录 前言 一、css3实现布局的方式有哪些&#xff1f; 1.flex布局 2.grid布局 二、jquery的扩展机制&#xff1f; 三、jquery动画和css实现动画的本质区别&#xff1f; 四、不使用css的动画&#xff0c;如何实现盒子从左到右移动&#xff1f; 五、使用过的框架&#xf…...

Java基础常见面试题(七)

序列化和反序列化 Java序列化与反序列化是什么&#xff1f; Java序列化是指把Java对象转换为字节序列的过程&#xff0c;而Java反序列化是指把字节序列恢复为Java对象的过程。 序列化&#xff1a; 序列化是把对象转换成有序字节流&#xff0c;以便在网络上传输或者保存在本地…...

【springmvc】报文信息转换器

HttpMessageConverter HttpMessageConverter&#xff0c;报文信息转换器&#xff0c;将请求报文转换为Java对象&#xff0c;或将Java对象转换为响应报文 HttpMessageConverter提供了两个注解和两个类型&#xff1a; RequestBody&#xff0c; ResponseBody&#xff0c; Reques…...

C++实现分布式网络通信框架RPC(3)--rpc调用端

目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中&#xff0c;我们已经大致实现了rpc服务端的各项功能代…...

C++_核心编程_多态案例二-制作饮品

#include <iostream> #include <string> using namespace std;/*制作饮品的大致流程为&#xff1a;煮水 - 冲泡 - 倒入杯中 - 加入辅料 利用多态技术实现本案例&#xff0c;提供抽象制作饮品基类&#xff0c;提供子类制作咖啡和茶叶*//*基类*/ class AbstractDr…...

CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型

CVPR 2025 | MIMO&#xff1a;支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题&#xff1a;MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者&#xff1a;Yanyuan Chen, Dexuan Xu, Yu Hu…...

React Native 开发环境搭建(全平台详解)

React Native 开发环境搭建&#xff08;全平台详解&#xff09; 在开始使用 React Native 开发移动应用之前&#xff0c;正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南&#xff0c;涵盖 macOS 和 Windows 平台的配置步骤&#xff0c;如何在 Android 和 iOS…...

如何将联系人从 iPhone 转移到 Android

从 iPhone 换到 Android 手机时&#xff0c;你可能需要保留重要的数据&#xff0c;例如通讯录。好在&#xff0c;将通讯录从 iPhone 转移到 Android 手机非常简单&#xff0c;你可以从本文中学习 6 种可靠的方法&#xff0c;确保随时保持连接&#xff0c;不错过任何信息。 第 1…...

【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)

骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术&#xff0c;它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton)&#xff1a;由层级结构的骨头组成&#xff0c;类似于人体骨骼蒙皮 (Mesh Skinning)&#xff1a;将模型网格顶点绑定到骨骼上&#xff0c;使骨骼移动…...

UR 协作机器人「三剑客」:精密轻量担当(UR7e)、全能协作主力(UR12e)、重型任务专家(UR15)

UR协作机器人正以其卓越性能在现代制造业自动化中扮演重要角色。UR7e、UR12e和UR15通过创新技术和精准设计满足了不同行业的多样化需求。其中&#xff0c;UR15以其速度、精度及人工智能准备能力成为自动化领域的重要突破。UR7e和UR12e则在负载规格和市场定位上不断优化&#xf…...

OpenLayers 分屏对比(地图联动)

注&#xff1a;当前使用的是 ol 5.3.0 版本&#xff0c;天地图使用的key请到天地图官网申请&#xff0c;并替换为自己的key 地图分屏对比在WebGIS开发中是很常见的功能&#xff0c;和卷帘图层不一样的是&#xff0c;分屏对比是在各个地图中添加相同或者不同的图层进行对比查看。…...

网络编程(UDP编程)

思维导图 UDP基础编程&#xff08;单播&#xff09; 1.流程图 服务器&#xff1a;短信的接收方 创建套接字 (socket)-----------------------------------------》有手机指定网络信息-----------------------------------------------》有号码绑定套接字 (bind)--------------…...

Android第十三次面试总结(四大 组件基础)

Activity生命周期和四大启动模式详解 一、Activity 生命周期 Activity 的生命周期由一系列回调方法组成&#xff0c;用于管理其创建、可见性、焦点和销毁过程。以下是核心方法及其调用时机&#xff1a; ​onCreate()​​ ​调用时机​&#xff1a;Activity 首次创建时调用。​…...