虚拟DOM的本质和目的
目录:
一、虚拟DOM的介绍
二、DOM的本质
三、react中的虚拟DOM
四、虚拟DOM的目的
五、虚拟DOM的原理流程
六、虚拟DOM示例
七、DOM与虚拟DOM的区别
一、虚拟DOM的介绍
1. DOM的本质
虚拟DOM是框架中的概念,它主要的目的是为了实现DOM元素的高效更新
浏览器中的概念,用S对象来表示页面上的元素,并提供了操作DOM对象的API;
2.React中的虚拟DOM
框架中的概念,是程序员用S对象来模拟页面上的DOM和DOM嵌套;使用原生JavaScript或jQuery直接操作DOM元素时,很大可能会触发回流事件,此时浏览器需要重新渲染页面,设置整个文档,计算DOM节点浪费了性能,而且效率低,非常影响用户体验。
3.虚拟DOM的目的
为了实现页面炉,DOM元素的高效更新;
提供与真实DOM节点所对应的虚拟节点vnode
将虚拟节点vnode和旧虚拟节点oldVnode进行对比,然后更新视图
4. 虚拟DOM原理流程
(1)用JavaScript模拟DOM树,并渲染这个DOM树
(2)比较新老DOM树,得到比较的差异对象
(3)把差异对象应用到渲染的DOM树
5.虚拟DOM示例
当前我们有如下表格
需求:
点击列头,实现对应表格数据的排序;比如点击时间这一列,时间从大到小排序;点击新关注人数,就按照新关注人数排序
1.表格中的数据从哪来的:从数据库查询查询而来:
2.这些查询到的数据,存放到浏览器内存:数据在浏览器的内存中存放着,而且是以对象数组的形式来表示的,通过ajax和网络传输。
3.这些数据,是如何渲染到页面上的,方案有很多种。
如何把数据形成表格形式
方案1:
手动 for循环整个数组,然后手动拼接字符串str+='<tr></tr>',最终会得到完整的tr,放置到表格中即可查看
方案2:
使用模板引擎,art-template
区别:模板引擎更加方便,内部本质也是提供字符串,最大区别方便程序员使用
4.思考:
上述的方案,有没有性能上的问题?
如果第一次来渲染,必须for循环,若不是第一次渲染,假如用户点时间表头就会点击事件触发,然后就会对事件进行排序,这个表格的数据是从数组得来的,也就是看到的就是数组里的数据,但他的数据是乱的
在事件中拿到数据进行排序,表格是经for循环而来。内存中交换,数组顺序将会改变,把最新的数组重新渲染到表格
5.如果用户点击了[时间]这一列,想按照时间从大到小排序:
1)第一步:触发点击事件,在事件中,把内存中的对象数组,重新排序。
2)第二步:当排完序之后,页面是旧的,但是内存中的对象数组是新的。
3)第三步:想办法把最新的数组,重新渲染到页面上。(重点思考第三步有没有性能上的问题)
假设说之前的数据是20、21,点击时间之后,20和21两行就会交换一下位置,而后面的数据不需要排序,所以只操作这两行数据就行,这样整个数组的数据就排序完成。然后就要用第三步对最新的数组进行重新渲染到页面上,或者手动for循环,那就需要把整个数组重新渲染一遍,但是后面这几行数据他没变,那就没必要去重新渲染,因为如果重新渲染的话,还会有一些性能上的损耗。其实最好的一个方法那就是只交换20、21这两行的位置就可以了,后续就不需要管。
若按照时间排序,后面的数据是不需要后换的,只需要互换操作的数据,不需要重新被渲染。两行变只需要交换变的行
6.分析与总结:上述方案,只是实现了把数据染到页面上的能力,但是并没有把性能做到最优。
7.如何才能把性能做到最优:
按需求渲染页面: (只重新渲染更新的数据所对应的页面元素)
假如表格很长,有千行,会涉及数据的重复渲染,性能就会低下i
8.如何实现页面的按需渲染呢?
1、通过分析,DOM树,一个网页是一个树结构的形式,标签是嵌套的DOM树,DOM树是浏览器提供
2、DOM树概念:
一个网页呈现的过程:
(1)浏览器请求服务器获取页面HTML代码
(2) 浏览器要现在内存中,解析DOM结构,并在浏览器内存中,渣染出一颗DOM树;
(3) 浏览器把DOM树,呈现到页面上;
前端程序员进行按需更新
(4) 例子:
怎么实现DOM树,先定义两个DOM树这是之前的老表格,然后另一个是目前最新的那个表格。第一行、第二行、第三行、第四行,这是老表格里面DOM树,新表格那这里面也有第一行,第二行、第三行,第四行这每一行都是一一对应的。那接下来怎么才能实现安全中心?
对比看第一行和第一行旧的和现在是否一样,再看第二行是否一样。发现第一行数据变了,那就把第一行标记为是不是需要被安全更新,第二行对比发现也改变了,所以也需要安全更新。但是再往下,第三行和第四行是不是并没有任何改变?
那这两行就不需要去更改,这样的话,通过两颗树的对比就可以实现DOM树。
9.如何实现页面的按需更新?
通过对比进行按需更新,对比行与行的内容,两颗DOM树详细对比实现按需更新,进而对比,得到需要按需更新的DOM元素;
10.如何获取到新旧DOM树,从而实现DOM树的对比?
操作DOM是一定要通过它提供的API,浏览器里面会提供DOM、API,比如document的ID都是那些浏览器提供,要想要获取这个新旧DOM树,是要调用相关的API才能拿到,但是从脑海里面去搜索一遍,没有这样的API来获取DOM树的API,也就是浏览器里面并没有提供让我们程序员获取DOM树的API,是只能获取元素,不能获取DOM树。因此拿浏览器里面的DOM树是不现实的。
分析:浏览器中,并没有直接提供获取DOM树的API:
因此, 我们无法拿到浏览器内存中的DOM树,这条路已经走不通
11.程序员可以手动模拟新旧两棵DOM树,来实现对比的需求
12.程序员如何手动模拟DOM树?如何模拟一个DOM元素;
HTML不能模拟DOM元素,可以使用js对象模拟
<div id="mydiv" title="说实话,彬哥好帅</div>
比如:
<div id= mydiv" title= "说实话"data-index="0" >
彬哥好帅
//存放p标签
<p>哈哈哈</p>
</div>
Var div ={
//模拟div对象
tagName: 'div',
//属性赋值
attrs:{
//编号
id: 'mydiv',
//题目
title:说实话,
//日期索引,属性带杠必须引号包裹
'data-index': 'O'
}
//子节点,子元素
childrens; {
彬哥好帅,
},
//标签名为p
tagName;'p
//无属性,空对象
attrs:{}
//子节点
childrens:[
哈哈哈”
]
}
}
//元素嵌套通过此类方法实现
id: 'mydiv',
title:说实话123,
'data-index': 'O'
}
childrens; 【
彬哥好帅,
{
tagName;'p
attrs:{}
childrens:{
哈哈哈qqq”
}
}
}
//对比标签名和属性,子节点中的内容对比,使用DOM树逐层对比来实现
13.程序员手动模拟的这两棵新旧DOM树,就是React中虚拟DOM的概念:
总结:什么是虚拟DOM:
用JS对象的形式,来模拟页面上DOM嵌套关系: (虚拟DOM是以JS对象的形式存在的: )
React中虚拟DOM的概念:
本质:
用JS对象,来模拟DOM元素和嵌套关系:
目的:就是为了实现页面元素的高效更新:
例如:
任意一个网页比如说
一个网页呈现的过程:
浏览器请求服务器大取页面HTML代码
4、浏览器在现在内存中,解析DOM结构,并在浏览器内存中,渲染出一个DOM树:
浏览器把DOM时,呈现到页面上:
二、DOM和虚拟DOM的区别
1.DOM
浏览器中提供的一些概念;用js对象,表示页面上的元素,并提供了操作的api
(1) 真实的DOM类似于一个文档对象模型,页面上渲染出来的节点都是真实的DOM
(2) 可以直接更新HTML
(3) 元素更新,创建新的DOM
(4)操作DOM比较麻烦,消耗很大的内存
2.虚拟DOM
是框架中的概念;而是开发框架的程序员,手动用Js对象来模拟DOM元素和嵌套关系的
(1) 虚拟DOM是以Javascript的形式存在来描述DOM,创建虚拟DOM的目的就是将虚拟DOM更好的渲染到页面UI中,它与真实的DOM是一一对应的
(2) 不可以直接更新HTML
(3) 元素更新,更新JSX
(4)操作DOM方便,消耗少的内存,更新快
3.本质
用JS对象,来模拟DOM元素和嵌套关系
4.目的
就是为了实现页面元素的高效更新