首页 > 其他分享 >虚拟dom

虚拟dom

时间:2023-05-26 12:14:05浏览次数:28  
标签:el const dom length 虚拟 newChildren

虚拟dom

啥是虚拟dom

为什么要有这玩意

这玩意给前端造成了那些影响

怎么做一个玩具版本的虚拟dom

虚拟dom, 听名字应该就知道了, 假dom, 为什么要有假dom, 因为操作真dom太重了吗?

都说虚拟dom能提高性能, 真的吗?

let dom = createElement('div')
div.style.background = 'red'
div.style.borderRadius = '50%'
div.style.width = '200px'
div.style.height = '200px'
div.innerHTML = 'hahha'

上面是一段操作dom的代码, 就是说你再怎么虚拟, 到最后你还是要执行上面这些代码, 相当于, 在在操作实际dom前, 先通过对比新旧虚拟dom, 计算出dom要做那些更新, 如果你是一个dom高手, 你完全可以通过自己的规划直接去操作达到最好,最优的操作, 如果你是dom 杀手, 那就不行了, 操作太多次会带来性能问题, 这么看虚拟dom, 通过付出计算新旧dom的代价做到了让dom新手写的程序也不那么费性能, 显然它并不是最优的

这段话应该解释了第一个,第二个问题.

继续

插一下, 那么怎么成为一个dom高手,根据我一年的前端开发经验,我知道下面这些高效操作dom的方式, 看看能不能帮到你

  1. 缓存, 基本上写过代码你应该就知道这个, 上到redis,下到let a = xx.value(后面用到xx.value, 直接用a,减少依赖收集), 所以缓存dom元素, 肯定也能减少性能开销
  2. 使用querySelectorquerySelectorAll选择元素。这些方法使用css选择器语法,可以快速定位特定的元素
  3. 使用DocumentFragment创建新的DOM元素。这允许在不触发dom重排的情况下创建和修改一组元素
  4. 使用事件委托来处理事件。这使得只需将事件处理程序绑定到祖先元素,而不需要将其绑定到每个后代元素上
  5. 将多个dom操作合并到单个批处理中。通过一次性更新dom树可以减少浏览器的重绘次数,并提高页面性能
  6. CSS样式应用到类而不是单个元素。这可以减少CSS选择器的数量,并减少浏览器的计算负担
  7. 避免使用innerHTML来插入HTML,因为它会破坏现有的事件处理程序和数据绑定。相反,使用DOM API来创建和插入新的DOM元素

上面是一个小插曲.

接着说虚拟dom对前端造成了什么影响, 从coding体验上来看, 显然是变爽了, 无论是vuer,reacter, 都享受到了这个便利, 太酷了, 从前端发展上, 好像有很大的里程碑意义, 我从事前端时间不长, 不过我读过一些历史, 从过去的jquery时代到现在大前端时代, 显然虚拟dom, 是一项很给力的技术.

那么如何做一个玩具版的虚拟dom

// 虚拟DOM
const map = (tag, attrs, children) => {
	return { tag, attrs, children };
};

// 实际DOM
const h = (node) => {
	if (typeof node === 'string') {
		return document.createTextNode(node);
	}
	const el = document.createElement(node.tag);
	node.children.forEach(child => {
		el.appendChild(h(child));
	});
	return el;
};

// 渲染DOM
const render = (root, node) => {
	root.appendChild(h(node));
};

// 更新DOM
const update = (oldNode, newNode) => {
	// 如果tag不同,直接替换为新节点
	if (oldNode.tag !== newNode.tag) {
		oldNode.el.replaceWith(h(newNode));
	} else {
		// 更新attrs
		const el = oldNode.el;
		const newAttrs = newNode.attrs;
		const oldAttrs = oldNode.attrs;
		Object.keys(newAttrs).forEach(key => {
			const newVal = newAttrs[key];
			const oldVal = oldAttrs[key];
			if (newVal !== oldVal) {
				el.setAttribute(key, newVal);
			}
		});
		Object.keys(oldAttrs).forEach(key => {
			if (!(key in newAttrs)) {
				el.removeAttribute(key);
			}
		});
		// 更新children
		const newChildren = newNode.children;
		const oldChildren = oldNode.children;
		if (typeof newChildren === 'string') {
			if (newChildren !== oldChildren) {
				el.textContent = newChildren;
			}
		} else {
			for (let i = 0; i < newChildren.length; i++) {
				update(oldChildren[i], newChildren[i]);
			}
			if (oldChildren.length > newChildren.length) {
				for (let i = newChildren.length; i < oldChildren.length; i++) {
					oldChildren[i].el.parentNode.removeChild(oldChildren[i].el);
				}
			} else if (oldChildren.length < newChildren.length) {
				for (let i = oldChildren.length; i < newChildren.length; i++) {
					const newChild = h(newChildren[i]);
					el.appendChild(newChild);
				}
			}
		}
		// 更新节点的元素引用
		newNode.el = oldNode.el;
	}
};

// 初始化虚拟DOM并挂载到页面
const rootNode = document.querySelector('#app');
const vNode = vdom('div', {}, [vdom('p', {}, ['Count: 0']), vdom('button', { onClick: increment }, 'Increment')]);
const root = render(rootNode, h(vNode));
vNode.el = root.firstChild;

let count = 0;

// 更新虚拟DOM并重绘视图
function increment () {
	const newVNode = vdom('div', {}, [vdom('p', {}, [`Count: ${++count}`]), vdom('button', { onClick: increment }, 'Increment')]);
	update(vNode, newVNode);
	vNode.el = newVNode.el;
}




以上是一个简易版本的虚拟dom,以及diff算法实现

标签:el,const,dom,length,虚拟,newChildren
From: https://www.cnblogs.com/kelanmonkperson/p/17434381.html

相关文章

  • 统信UOS系统开发笔记(一):国产统信UOS系统搭建开发环境之虚拟机安装
    前言  开发国产应用,需要使用到统信UOS系统,之前已经开发过国产银河麒麟V4、V7和V10版本了,本次新项目使用到统信UOS,记录UOS虚拟机安装流程,方便快捷进行相关开发工作。<br>提前准备VMware16虚拟机软件  下载VM16版本及以上的vmware虚拟机版本,否则没有CentO8选项,自行百度下......
  • GPT虚拟直播Demo系列(一)|GPT接入直播间实现主播与观众互动
    摘要ChatGPT和元宇宙都是当前数字化领域中非常热门的技术和应用。结合两者的优势和特点,可以探索出更多的应用场景和商业模式。例如,在元宇宙中使用ChatGPT进行自然语言交互,可以为用户提供更加智能化、个性化的服务和支持;在ChatGPT中使用元宇宙进行虚拟现实体验,可以为用户提供更加真......
  • 瑞云科技助力番职院打造虚拟数字人,探索职业教育创新之路
    3月24-25日,教育部高等学校科学研究发展中心主办、广州番禺职业技术学院承办的2022-2023年职业教育示范性虚拟仿真实训基地建设工作推进会在中国广州举行。会议旨在指导各院校建好用好管好虚拟仿真示范实训基地,以数字化、网络化、智能化赋能职业教育高质量发展。会议期间,瑞云科技......
  • 01、虚拟机相关
     四、虚拟机快照通过拍摄虚拟机快照,可以完全克隆一份相同的已配置好的虚拟机,方便以后使用,免除重复创建系统的麻烦;虚拟机快照会存在IP冲突的情况;步骤1、关机--拍摄快照2、克隆主机3、IP冲突解决--改IP地址改最后一位3-254之间的任一数字   #查看网卡名......
  • Cisco® Catalyst® 8000V 边缘软件 (Catalyst 8000V) 17.11.1a 发布 - 虚拟路由器
    Cisco®Catalyst®8000V边缘软件(Catalyst8000V)17.11.1a发布-虚拟路由器CiscoCatalyst8000vEdgeSoftware,IOSXEReleaseDublin-17.11.1aED请访问原文链接:https://sysin.org/blog/cisco-catalyst-8000v/,查看最新版。原创作品,转载请保留出处。作者主页:sysin.or......
  • jsdom, proxy对象(补环境神器)以及抠代码总结的问题
    jsdomconstjsdom=require('jsdom')const{JSDOM}=jsdomconstfs=require('fs')options={url:'http://match.yuanrenxue.com/match/2',referrer:'http://match.yuansrenxue.com/match/2',......
  • 如何使用Map处理Dom节点
    本文浅析一下为什么Map(和WeakMap)在处理大量DOM节点时特别有用。我们在JavaScript中使用了很多普通的、古老的对象来存储键/值数据,它们处理的非常出色:constperson={firstName:'Alex',lastName:'MacArthur',isACommunist:false};但是,当你开始处理较大的......
  • javascript web api,bom&dom
    Api1.获取dom元素constx=document.querySelector('选择器')querySelectorAll返回的是伪数组2.操作元素内容对象.innerText对象.innerHTML会解析标签3.操作元素样式属性1.style<script>  constdiv=document.querySelector('.box')  box.style.width=......
  • XML解析之DOM解析
    XML解析之DOM解析XML结构是一种树型结构,处理步骤都差不多,Java己经将它们封装成了现成的类库。目前流行的解析方法有三种,分别为DOM、SAX和DOM4j。本文将讲解DOM解析。DOM(DocumentObjectModel,文档对象模型)是W3C组织推荐的处理XML的一种方式。它是一种基于对象的API,......
  • 深入理解 python 虚拟机:花里胡哨的魔术方法
    深入理解python虚拟机:花里胡哨的魔术方法在本篇文章当中主要给大家介绍在cpython当中一些比较花里胡哨的魔术方法,以帮助我们自己实现比较花哨的功能,当然这其中也包含一些也非常实用的魔术方法。深入分析hash方法在Python中,__hash__()方法是一种特殊方法(也称为魔术方法......