面试官问:如何理解VirtualDOM?-创新互联
一、vdom是什么?
创新互联建站服务项目包括房县网站建设、房县网站制作、房县网页制作以及房县网络营销策划等。多年来,我们专注于互联网行业,利用自身积累的技术优势、行业经验、深度合作伙伴关系等,向广大中小型企业、政府机构等提供互联网行业的解决方案,房县网站推广取得了明显的社会效益与经济效益。目前,我们服务的客户以成都为中心已经辐射到房县省份的部分城市,未来相信会继续扩大服务区域并继续获得客户的支持与信任!vdom是虚拟DOM(Virtual DOM)的简称,指的是用JS模拟的DOM结构,将DOM变化的对比放在JS层来做。换而言之,vdom就是JS对象。
如下DOM结构:
- Item1
- Item2
映射成虚拟DOM就是这样:
{ tag: "ul", attrs: { id: "list" }, children: [ { tag: "li", attrs: { className: "item" }, children: ["Item1"] }, { tag: "li", attrs: { className: "item" }, children: ["Item2"] } ] } 复制代码
二、为什么要用vdom?
现在有一个场景,实现以下需求:
[ { name: "张三", age: "20", address: "北京" }, { name: "李四", age: "21", address: "武汉" }, { name: "王五", age: "22", address: "杭州" }, ] 复制代码
将该数据展示成一个表格,并且随便修改一个信息,表格也跟着修改。 用jQuery实现如下:
Document 复制代码
这样点击按钮,会有相应的视图变化,但是你审查以下元素,每次改动之后,table标签都得重新创建,也就是说table下面的每一个栏目,不管是数据是否和原来一样,都得重新渲染,这并不是理想中的情况,当其中的一栏数据和原来一样,我们希望这一栏不要重新渲染,因为DOM重绘相当消耗浏览器性能。
因此我们采用JS对象模拟的方法,将DOM的比对操作放在JS层,减少浏览器不必要的重绘,提高效率。
当然有人说虚拟DOM并不比真实的DOM快,其实也是有道理的。当上述table中的每一条数据都改变时,显然真实的DOM操作更快,因为虚拟DOM还存在js中diff算法的比对过程。所以,上述性能优势仅仅适用于大量数据的渲染并且改变的数据只是一小部分的情况。
虚拟DOM更加优秀的地方在于:
1、它打开了函数式的UI编程的大门,即UI = f(data)这种构建UI的方式。
2、可以将JS对象渲染到浏览器DOM以外的环境中,也就是支持了跨平台开发,比如ReactNative。
另外大家可以参考尤大的一些回答: www.zhihu.com/question/31…
三、使用snabbdom实现vdom
snabbdom地址:github.com/snabbdom/sn…
这是一个简易的实现vdom功能的库,相比vue、react,对于vdom这块更加简易,适合我们学习vdom。vdom里面有两个核心的api,一个是h函数,一个是patch函数,前者用来生成vdom对象,后者的功能在于做虚拟dom的比对和将vdom挂载到真实DOM上。
简单介绍一下这两个函数的用法:
h('标签名', {属性}, [子元素])
h('标签名', {属性}, [文本])
patch(container, vnode) container为容器DOM元素
patch(vnode, newVnode)
现在我们就来用snabbdom重写一下刚才的例子:
Document 复制代码
再进入页面:
你会发现,只有改变的栏目才闪烁,也就是进行重绘,数据没有改变的栏目还是保持原样,这样就大大节省了浏览器重新渲染的开销。四、diff算法
1、什么是diff算法?
所谓diff算法,就是用来找出两段文本之间的差异的一种算法。
作为一个前端,大家经常会听到diff算法这个词,其实diff并不是前端原创的算法,其实这一个算法早已在linux的diff命令中有所体现,并且大家常用的git diff也是运用的diff算法。
2、vdom为什么用diff算法
DOM操作是非常昂贵的,因此我们需要尽量地减少DOM操作。这就需要找出本次DOM必须更新的节点来更新,其他的不更新,这个找出的过程,就需要应用diff算法。
3、vdom中diff算法的简易实现
以下代码只是帮助大家理解diff算法的原理和流程,不可用于生产环境。
将vdom转化为真实dom:
const createElement = (vnode) => { let tag = vnode.tag; let attrs = vnode.attrs || {}; let children = vnode.children || []; if(!tag) { return null; } //创建元素 let elem = document.createElement(tag); //属性 let attrName; for (attrName in attrs) { if(attrs.hasOwnProperty(attrName)) { elem.setAttribute(attrName, attrs[attrName]); } } //子元素 children.forEach(childVnode => { //给elem添加子元素 elem.appendChild(createElement(childVnode)); }) //返回真实的dom元素 return elem; } 复制代码
用简易diff算法做更新操作:
function updateChildren(vnode, newVnode) { let children = vnode.children || []; let newChildren = newVnode.children || []; children.forEach((childVnode, index) => { let newChildVNode = newChildren[index]; if(childVnode.tag === newChildVNode.tag) { //深层次对比, 递归过程 updateChildren(childVnode, newChildVNode); } else { //替换 replaceNode(childVnode, newChildVNode); } }) } 复制代码
参考资料:
知乎尤雨溪回答
揭秘一线互联网企业 前端JavaScript高级面试
前端进阶与面试指南
另外有需要云服务器可以了解下创新互联scvps.cn,海内外云服务器15元起步,三天无理由+7*72小时售后在线,公司持有idc许可证,提供“云服务器、裸金属服务器、高防服务器、香港服务器、美国服务器、虚拟主机、免备案服务器”等云主机租用服务以及企业上云的综合解决方案,具有“安全稳定、简单易用、服务可用性高、性价比高”等特点与优势,专为企业上云打造定制,能够满足用户丰富、多元化的应用场景需求。
网站题目:面试官问:如何理解VirtualDOM?-创新互联
网页路径:http://ybzwz.com/article/dceccg.html