壹 ❀ 引
虚拟DOM
(Virtual DOM)在前端领域也算是老生常谈的话题了,若你了解过vue
或者react
一定避不开这个话题,因此虚拟DOM
也算是面试中常问的一个点,那么通过本文,你将了解到如下几点:
- 虚拟
DOM
究竟是什么? - 虚拟
DOM
的优势是什么?解决了什么问题? - 虚拟
DOM
的性能比操作原生DOM
要快吗? react
中的虚拟DOM
是如何生成的?react
是如何将虚拟DOM
转变成真实dom
的?
阅读前建议与提醒:
- 本篇文章可能比较长,建议挑一个空闲的时间段阅读,还请保持耐心,我将以通俗易懂的口吻带你了解这些问题。
- 本文源码分析部分
react
版本为17.0.2
,无须担心低版本源码分析对你之后面试帮助不大的问题。 - 如果可以,泡上一杯性温的茶或者咖啡,保持一个舒服的姿势会让你阅读更加愉快。
那么本文开始。
贰 ❀ 在虚拟dom之前
在聊虚拟DOM
之前,我还是想先聊聊在没有虚拟DOM
概念的时候,我们是如何更新页面的,所以在这里我将先引出前端框架(库)的发展史,通过这个变迁过程也便于大家理解虚拟dom的出现到底解决了什么问题。
贰 ❀ 壹 石器时代jqery
其实在15年以及更早之前,前端面试涉及到性能优化问题,往往都会提到尽可能少的操作DOM
这一点。为什么呢?因为在原生JS的年代,前端项目文件都明确分为html、js
与css
三种,我们在js
中获取DOM
,并为其绑定事件,通过事件监听感知用户在UI层的操作,并随之更新DOM
,从而达到页面交互的目的:
而在后面,jqery
的出现极大简化了开发者操作DOM
的成本,抹平了当时不同浏览器操作DOM
的API
差异,为当时苦于ie
以及不同浏览器自研API
的开发者解决了不少兼容性问题,当然JQ
也并未改变开发者在JS
层直接操作DOM
这一现状。
那么我们为什么说要尽可能少的操作DOM
呢,这里就涉及到重绘与回流两个概念,比如单纯修改颜色就会引发重绘,删除或新增一个DOM
节点就会引发回流和重绘,用户虽然无法感知这个过程,但对于浏览器而言也存在消耗性能。所以针对于回流,在此之后又提出了DocumentFragment
文档对象以优化多次操作DOM
的方案。简单理解就是,假如我要依次替换五个li
节点,那么我们可以创建一个DocumentFragment
对象保存这五个节点,然后一次性替换。
关于节流与重绘,若有兴趣可读读博主页面优化,谈谈重绘(repaint)和回流(reflow)一文。
关于DocumentFragment
可读读博主页面优化,DocumentFragment对象详解一文。
这些都是时代的眼泪,现在应该很少会有人提及,这里就不再赘述了。
贰 ❀ 贰 青铜时代angularjs
在JQ
之后,angularjs
(这里指angularjs1而非angular)横空出世,一招双向绑定在当时更是惊为天人,除此之外,angularjs
的模板语法也格外惊艳,我们将所有与数据挂钩的节点通过{{}}
包裹(vue在早期设计上大量借鉴了angularjs),比如:
<span>{{vm.name}}</span>
之后 view
视图层就自动与 Model
数据层进行挂钩(MVC那一套),只要 Model
层数据发生变化,view
层便自动更新。angularjs
的这种做法,彻底将开发者从操作 DOM
上解放了出来(为jq没落埋下伏笔),自此之后开发者只用专注 Model
层的数据加工以及业务处理,至于页面如何渲染全权交给 angularjs
底层处理即好了。
但需要注意的是,angularjs
在当时并没有虚拟dom
的概念,那它是怎么做感知数据层变化以及更新视图层的呢?angularjs
有一套脏检测机制$digest
,html
中凡是使用了模板语法{{}}
或者ng-bind
指令的部分,都会被加入到脏检测的warchers
列表中,它是一个数组,之后只要用户通过ng-click(与传统click不同,内置绑定了触发脏检测的机制)
等方法改变了Model
的数据,angularjs
就会从顶层rootScope
向下递归,依次访问每个子scope
中的warchers
列表,并对其中监听的部分做新旧对比,如果不同则进行数据替换,以及DOM
层的更新。
但是你要想想,一个应用那么大的结构,只要某一个数据变化了就得从顶层向下对比N个子 scope
中 warchers
下的所有监听对象,全量对比的性能有多差可想而知,angularjs
自身也意识到了这点,所以之后直接放弃了 angularjs
的维护转而新开了 angular
项目。
对于 标签:dom,react,var,虚拟,props,组件
来源: https://www.cnblogs.com/echolun/p/16359890.html
本站声明:
1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。
angularjs
脏检测感兴趣可以读读博主深入了解angularjs中的