前端开发到此为止,为什么Vue和React都需要虚拟DOM。答:DOM操作慢,JS可以快,但真的是这样吗?从零开始:什么是虚拟DOM?VirtualDOM本质上是js和DOM的映射。它在心理上被表示为一个可以描述DOM结构及其属性信息的js对象。react中的js对象表现如下:就这个例子来说,总结起来,虚拟DOM应该有以下两个特点:虚拟DOM是一个js对象虚拟DOM是对真实DOM的描述,前世今生virtualDOM学习一个新的知识点,不仅要了解这个东西是什么,我觉得更重要的是这个东西解决了什么问题。任何新技术都是无源之水、无本之木。我觉得等我们了解了场景再谈实现就水到渠成了。学习虚拟DOM也是如此。要想学好虚拟DOM,我想大家应该对前端的开发有一个大概的了解。请关注我的公众号,从零手写精简Vue2/Vue3,从零手写Promise完整源码,从零使用typescript手工制作轮子包axios,教你搭建node+egg项目等优质资源。赶快关注公众号,发送“1024”获取吧!!!nativejs下的DOM操作早就很久以前了。当页面仅用于简单显示时,使用的DOM操作不是很频繁。那时候还是表格布局,页面小哥们会花很多时间去实现页面的静态布局,比如html+css这样的展示页面,最后加少量的js实现一些类似于隐藏显示选项卡的交互。现阶段,网页男孩也被称为cuttu男孩。不需要很多DOM操作,没有很多网页连业务逻辑都没有,那时候我们还过得很幸福。这样的网页,原生js就够了。解放兼容jQuery时代随着时代的发展,产品经理越来越不满足于这些简单、枯燥、死板的交互方式,于是开始追求丰富的用户体验。映射到实现中伴随着大量的DOM操作。在实际开发中,网页人逐渐发现原生js提供的DOM操作API太TM难用了。于是有大牛开发了jQuery库来解决js在操作DOM方面效果不佳的问题。顺带一提,兼容让人一提到就想跑的IE系列。这真的很令人兴奋。jQuery的一系列链式操作和可组合的插件扩展,用起来真的很神奇。jQuery的DOM操作简单快捷,让网页小白们用的少一些。现在读起来还是很舒服的。当年能够称霸江湖,也是实至名归。虽然这有助于人们以更舒适的姿势操作DOM,但人们逐渐发现,频繁地因数据变化而操作DOM也是一个大问题,这着实伤了网页男孩的心。早期的模板解决方案jQuery就像一个可以随意调用的建筑工人。想要翻新楼,就得告诉他先去拿工具,然后找到墙,再把他扶起来,用水泥砖砌起来。加上表面……这样的操作真的很累。如果有工头负责,我直接告诉他我要把墙改造成什么,后面的事情他监督起来就方便多了。而模板引擎就是那个工头的原型。我们来看这样一个例子。比如现在我有一个班级花名册,数据如下:conststudents=[{name:'小明',stu_no:'001'},{name:'刚子',stu_no:'002'},{name:'LiHua',stu_no:'003'}]前端要以列表的形式显示。这里我们使用ejs的语法:
- <%students.forEach(student=>{%>
<%=student.name%>/span>
<%=student.stu_no%>
<%})%>/ul>然后在文档document中插入htmlconsttargetContainer=document.getElementById('target')constinnerHTML=ejs.render({students:students})targetContainer.innerHTML=innerHTML用模板写项目还是蛮爽的,只需要关注数据层的变化即可。当数据改变时,我们再次进行渲染。至此,模板引擎已经有了数据渲染页面的雏形。但也有相应的不足,比如:数据量巨大时总是重新渲染,性能不尽如人意。实际应用场景基本仅限于“字符串拼接”及其死板,数据变化需要人工重新渲染。做拼接……即便如此,模板引擎还是开了个好头,在思路上迈出了新的一步——把大量精力花在数据上,而不是渲染视图上。所以核心问题还是出在性能上。每次数据更改时,都必须彻底重新渲染整个列表视图。谁受得了?虚拟DOM诞生了,于是一群有志之士(以下内容纯属捏造)提出,既然模板引擎每次都要重新渲染,那我就不重新渲染了,直接重新渲染已更改的DOM。由于操作真实DOM的性能损失很大,所以我操作假DOM就可以了。于是,虚拟DOM诞生了。那么我们在初始渲染时对比一下模板引擎和虚拟DOM的渲染过程:模板引擎的渲染是:数据+模板-->直接渲染到真实DOM-->当挂载到虚拟DOM的渲染页面的DOM:data+Template-->VirtualDOM-->RealDOM-->虚拟DOM中挂载到页面的模板应该有自己的特性类模板,像React中的jsx本质上不是模板,而是一种视觉上类似于模板的JS语法糖。从上面的对比可以看出,虚拟DOM的渲染有更多的虚拟DOM层。这个缓存层的好处是:当DOM有少量更新时,重新渲染时进行diff操作,定位到需要修改的部分并生成patchset,然后进行patch制成。虚拟DOM的出现真的是因为性能吗?故事的发展似乎要靠表演。从模板引擎到虚拟DOM发展的主要矛盾似乎都指向了性能。但是React引入虚拟DOM的初衷真的是为了性能吗?我们来做一下模板引擎和虚拟DOM在不同场景下的性能对比。必须在不同的场景下进行比较。撇开场景谈技术,都是耍流氓。从流程上来说,模板引擎和虚拟DOM的前半部分都属于js的范畴。比如模板引擎生成html字符串,虚拟DOM渲染中虚拟DOM的生成,以及两次更新的虚拟DOM之间的diff,都在js中,不涉及真正的DOM操作。与这两次相比,字符串拼接的性能损失显然微不足道,而且diff中涉及的遍历和递归相对字符串拼接也比较耗时,所以在js范围内,模板引擎肯定胜出。但是在真正DOM操作的最后一步,两者确实不相上下。这时候就真的需要对比一下场景了:如果数据量很大,页面上渲染了上万个列表,但是只需要改变其中的一两个,就算模板引擎坏了,也不如虚拟DOM的diff补丁。但是,如果数据内容变化很大,以至于differenceupdate和fullupdate很接近,或者fullupdate已经做完了,那么遍历和递归几万次就够client的diff喝一壶了。所以在这两种极端情况下,各有各的优势。其实这很像人生,总是在两者之间做出选择。在不同的场景下,两者是无法区分的。但必须加以区分。在实际开发中,无论是Vue还是React,我觉得变化最多的是vm.xxx=xxx或者this.setState({xxx:xxx}),只有极少数的属性变化,即使xxx是一个数组,也是重新分配的过程。说了这么多,所有的证据似乎都在指向性能的提升,即使我们分析后做出取舍,也只是在性能考虑的范围内。不过,我想说的是,我之前说的其实都是废话。其实我想说的是:虚拟DOM的价值不仅仅在于性能。您可能不同意我认为的虚拟DOM。就像看美女一样,因为审美的差异,大家未必会认同她是美女。我给出的可能不是标准答案。我认为虚拟DOM解决了以下几个关键问题:页面性能提升:虽然与我们之前的论点相比,虚拟DOM不是最优方案,但在大多数场景下,虚拟DOM可以给你页面性能不错,它为你提供具有更酷的开发模式。开发效率的提升:从前端发展历程的描述可以看出,DOM操作的每一次创新,背后都是开发效率的提升。不得不提的是,在React或者Vue时代,对于同一个页面,我们的开发效率提升了很多。至于开发单一的将输入框内容输出到页面的mvvm模式,引入Vue或React可以很快搞定。跨平台问题:VirtualDOM是对渲染内容的抽象描述,解耦了视图层和渲染层。这一层渲染层的描述可以是web、native、applet等多端,可能只需要一个代码就可以在不同的端工作。毕竟,即使是Vue3,也是将DOM操作的内容放在一个独立的runtime-dom.js模块中,目的就是在多个终端操作渲染层的内容,实现跨平台的可能。总结本次分享回顾的前端操作DOM的发展历程,了解虚拟DOM的定位和存在的问题,然后比较虚拟DOM和模板引擎的渲染差异和性能差异。最后对虚拟DOM出现的原因进行了总结。另:文中知识点如有表述不当或错误之处,欢迎留言批评指正,共同进步!