当前位置: 首页 > 科技观察

VirtualDOM如何演变成RealDOM

时间:2023-03-12 02:44:18 科技观察

前言Vue和React的Render功能都涉及到VirtualDOM的概念。VirtualDOM也是性能优化的重要一环。同时突破了直接操作真实DOM的瓶颈。本文以下列问题描述VirtualDOM。1、为什么要操作虚拟DOM?2、什么是虚拟DOM?3.教你实现虚拟DOM和渲染真实DOM。希望阅读本文后,您能够深入了解虚拟DOM,并从开发和面试中受益。为什么我们需要操作虚拟DOM?为了帮助我们更好地理解为什么需要操作虚拟DOM,我们先从浏览器渲染HTML文件时需要做些什么说起:浏览器渲染机制大致可以分为以下5个步骤:1.创建DOM树2.创建样式规则3。构建渲染树4。布局布局5。DrawPainting过去我们使用原生JavaScript和jquery来操作真实的DOM时,浏览器会从构建DOM开始🌲并执行从头到尾的渲染过程。在一次开发中,如果产品告诉你一个需求,你需要在一次操作中更新10个DOM节点。理想状态是浏览器一次性构建DOM树,然后进行后续操作。但是浏览器并不是那么聪明。收到第一个更新DOM的请求后,不知道后面还会有9次更新操作,所以会立即执行流程,最后执行了10次流程。过了一会儿,产品经理把你叫过来,让你改需求。这时候就需要重新更新DOM了。那么这段时间之前的10次DOM操作,就是在浪费性能和情绪。即使计算机硬件不断更新迭代,操作DOM的成本依然昂贵,频繁操作DOM仍会导致页面卡顿,影响用户体验。一个真实的DOM节点,即使是最简单的div也包含了很多属性,你可以打印出来直观感受一下:这么多属性,如果每次都更新DOM结构,一次,两次,三次……100次……一千次……,可想而知这是多么庞大的数据量。所以虚拟DOM就是为了解决这个浏览器性能问题而设计的。比如前面的例子,如果一次操作有10个更新DOM的动作,那么虚拟DOM不会立即对DOM进行操作,而是会针对这10个更新DOM的动作通过Diff算法生成一个js对象,然后通知浏览器执行一次性绘图工作,这样可以避免很多不必要的计算。什么是虚拟DOM?VirtualDOM[2]就是我们上面提到的js对象。它本质上是JS和DOM之间的缓存。它可以比作CPU和硬盘。由于硬盘很慢,我们在它们之间添加了一个缓存;由于DOM太慢了,我们在他们的JS和DOM之间添加了一个缓存。CPU(JS)只对内存(VirtualDOM)进行操作,最后将变化写入硬盘(DOM)。直接操作内存中的JS对象速度明显更快。functionvnode(tag,data,key,children,text){return{tag,data,key,children,text}}举个栗子:如果我们有这样一个DOM树前端简报

  • vue
  • 那么,我们如何使用js对象来对应这棵树呢?{tag:'ul',//元素标签数据:{//属性类:'list'},key:'',text:'',//文本内容children:[{tag:"li",data:{class:"item"},key:'',text:'',children:[{tag:undefined,data:undefined,key:undefined,text:'前端简报',children:[]}]},{tag:"li",data:"",key:'',text:'',children:[{tag:undefined,data:undefined,key:undefined,text:'vue',children:[]}]}]//子元素}由此我们可以看出:DOM树的信息是可以用JavaScript对象来表示的,反过来我们也可以利用JavaScript对象所表示的树结构来构建一个真正的DOM树。实现虚拟DOM渲染真实DOM有了JavaScript对象后,如何将其转化为真实的DOM树结构?ul和li在js对象中,页面上没有这个结构,所以需要将ul和li转换成and标签和text标签我们定义Vnode为:{tag:undefined,data:undefined,key:undefined,text:'vue',children:[]}这样我们就可以通过判断tag的类型来判断创建的element的类型。functioncreateElm(vnode){let{tag,data,children,key,text}=vnode;if(typeoftag=="string"){vnode.el=document.createElement(tag);//创建元素并放置在vnode.el上children.forEach(child=>{vnode.el.appendChild(createElm(child))})}else{vnode.el=document.createTextNode(text);//创建文本}returnvnode.el}如果子节点存在并且也是虚拟DOM,我们递归调用创建子节点。创建DOM树结构后,我们需要设置节点的属性,即处理虚拟DOM中的数据属性。functionupdateProperties(vnode){letel=vnode.el;letnewProps=vnode.data||{};for(letkeyinnewProps){if(key=="style"){for(letstyleNameinnewProps.style){el.style[styleName]=newProps.style[styleName];}}elseif(key=="class"){el.className=newProps.class;}else{el.setAttribute(key,newProps[key]);}}}在我们创建元素标签之前然后调用updateProperties方法将上面创建的真实DOM结构vnode.el添加到文档中来呈现我们需要的真实DOM结构letparentElm=document.getElementById("app").parentNode;获取上一个app的父bodyparentElm.insertBefore(createElm(vnode),document.getElementById("app").nextSibling);//在body中旧app之后插入真正的domparentElm.removeChild(document.getElementById("app")));//删除旧的Node总结以上就是本文的全部内容,我想大家现在应该明白了什么是虚拟DOM的概念,以及虚拟DOM是如何实现真实DOM渲染的。其中,使用了主要使用子节点的递归。下一篇文章将讲解虚拟节点的diff算法,敬请期待。参考资料[1]VirtualDOM简介:https://www.jianshu.com/p/616999666920[2]如何实现一个VirtualDOM算法:'https://github.com/livoras/blog/issues/13'【编辑推荐】incaseformat蠕虫大爆发!20多岁删除用户文件长文干货|手写自定义持久层框架!“远程删除照片”?个人信息安全不容践踏大年三十,让我们用JavaScript在你的网页上燃放烟花吧21世纪二十年过去了!十年前的这些场景,你还记得吗?