千锋教育-做有情怀、有良心、有品质的职业教育机构

400-811-9990
手机站
千锋教育

千锋学习站 | 随时随地免费学

千锋教育

扫一扫进入千锋手机站

领取全套视频
千锋教育

关注千锋学习站小程序
随时随地免费学习课程

上海
  • 北京
  • 郑州
  • 武汉
  • 成都
  • 西安
  • 沈阳
  • 广州
  • 南京
  • 深圳
  • 大连
  • 青岛
  • 杭州
  • 重庆
当前位置:长沙千锋IT培训  >  面试技巧  >  长沙IT培训程序员面试题:DOM DIFF

长沙IT培训程序员面试题:DOM DIFF

来源:千锋教育
发布人:千锋长沙
时间: 2021-03-19 16:19:00

        在程序员的职业生涯中,无论是在跳槽时还是晋升时都会遇到各式各样的面试,那么就技术层面上而言,这篇长沙IT培训程序员面试题:DOM DIFF希望能给你帮助。

        通过JS层面的计算(逐层比对虚拟DOM对象),生成patch对象(即补丁对象),然后对补丁进行解析和重新渲染

        对树进行分层比较,两棵树只会对同一层次的节点进行比较(不会跨节点比较)

4.png

        React 只会简单的考虑同层级节点的位置变换,而对于不同层级的节点,只有创建和删除操作

4.png

        可以处理同级节点顺序的改变每一层级进行对比的计算法则:深度优先遍历节点类型相同,看属性是否相同,如果不同,则产生属性的补丁包 {type:’ATTRS’,attrs:{class:’BB’}}新的DOM节点不存在,被删除了{type:’REMOVE’,index:xxx}节点类型不相同,直接替换即可 {type:’REPLACE’,newNode:xxx}文本的内容进行变化 {type:’TEXT’,text:xxx}

        function diff(oldTree,newTree){ let patchs = {}; //=>补丁包 按照层级放置补丁包 {1:[],2:[]} let index = 0; //=>比较的层级 //=>递归树,比较后的结果放到补丁包 walk(oldTree,newTree,index,patchs); return patchs;}function walk(oldNode,newNode,index,patchs){ let currentPatch={}; if(!newNode){ //=>新元素不存在,代表删除 currentPatch.push({ type:'EMOVE', index }); }else if(typeof oldNode==="string"&&typeof newNode==="string"){ //=>如果是文本,判断文本是否改变 if(oldNode!==newNode){ currentPatch.push({ type:'TEXT', text:newNode }); } }else if(oldNode.type===newNode.type){ //=>比较属性是否有更改 let attrs=diffAttr(oldNode.props,newNode.props);, if(Object.keys(attrs).length>0){ currentPatch.push({ type:'ATTRS', attrs }); } //=>如果有儿子节点,则遍历儿子 diffChildren( oldNode.props.childrren, newNode.props.childrren, index,patchs); }else{ //=>节点被替换了 currentPatch.push({ type:'REPACE', newNode }); } //=>当前本级查找,确实有补丁,我们放到最外层补丁包中 if(currentPatch.length>0){ patchs[index]=currentPatch; }}//=>比较儿子function diffChildren(oldChildren,newChildren,index,patchs){ oldChildrren.forEach((child,ind)=>{ walk(child,newChildren[ind],++index,patchs); })} //=>比较属性,生成补丁包function diffAttr(oldAttrs,newAttrs){ let patch={}; for(ley key in oldAttrs){ //=>属性不一样(可能是把老的中某个删除了,这样获取的结果可能是undefined) if(oldAttrs[key]!==newAttrs[key]){ patch[key]=newAttrs[key]; } } for(ley key in newAttrs){ //=>看老的节点中是否有这样一个属性(没有就是新增) if(!oldAttrs.hasOwnProperty(key)){ patch[key]=newAttrs[key]; } } return patch;}复制代码根据补丁重新渲染let patchs=diff(xxx,xxx); //=>两个虚拟DOMlet node;let index=0;walk(node);functon walk(node){ let currentPatch=patches[index++]; let cildNodes=node.childNodes; cildNodes.forEach(child=>walk(child)); if(currentPatch.length>0){ doPatch(node,currentPatch); }}function doPatch(node,patch){ patchs.forRach((item,index)=>{ switch(patch.type){ case 'ATTRS': for(let key in patch.attrs){ let val=patch.attrs[key]; if(val){ setAttr(node,key,val); }else{ node.removeAttribute(key) } } break; case 'TEXT': node.textContent=patch.text; break; case 'REPLACE': let newNode=(patch.newNode instanceof Element)?render(patch.newNode):document.createTextNode(patch.newNode); node.parentNode.replaceChild(newNode,node); break; case 'REMOVE': node.parentNode.removeChild(node); break; } }) }复制代码总结通过JS层面计算 === 对比的是虚拟DOM对象第一次加载页面,所有的内容都要重新渲染(语法解析 -> 虚拟DOM -> 真实DOM -> 浏览器渲染) =>第一次加载页面越少渲染越好上一次计算出来的虚拟DOM对象会存储起来,当状态或者其它数据改变,重新渲染组件(重新生成一套虚拟DOM对象)把重新生成的虚拟DOM 和 之前存储起来的虚拟 DOM进行对比=>把不一样的以补丁的形式存储起来(存储的还是对象)重新渲染的过程,只是把补丁渲染到页面中,原有渲染过但是没有改变的东西是不需要处理的

        本套学习内容由千锋长沙IT培训班韦老师撰写,版权归千锋教育学院所有,欢迎转载,转载请注明作者出处谢谢!

声明:本站稿件版权均属千锋教育所有,未经许可不得擅自转载。

猜你喜欢LIKE

最新文章NEW

相关推荐HOT

更多>>

快速通道 更多>>

最新开班信息 更多>>

网友热搜 更多>>