文章目录
-
- 一、虚拟DOM
- 二、Diff算法
一、虚拟DOM
- DOM树的概念:一个网页呈现的过程
1. 浏览器请求服务器获取页面HTML代码
2. 浏览器要现在内存中,解析DOM结构,并在浏览器内存中,渲染出一颗DOM树;
3. 浏览器把DOM树,呈现到页面上;
- 思考:
1. 如何才能把性能做到最优?
按需渣染页面;(只重新渲染更新的数据所对应的页面元素)
2. 如何实现页面的按需更新呢?
获取内存中的新旧两棵DOM,进行对比,得到需要被按需更新的DOM元素;
3. 如何获取到新旧DOM树,从而实现 DOM树的对比呢?
程序员手动模拟新旧两棵DOM树
分析:浏览器中,并没有直接提供 获取DOM树的API;因此,我们无法拿到浏览器内存中的DOM树;
4. 程序员如何手动模拟DOM树?
就是 React中虚拟DOM的概念;
5. 什么是虚拟DOM?
用JS对象的形式,来模拟页面上DOM嵌套关系;(虚拟DOM是以JS对象的形式存在的; )
6. 总结:
本质:用JS对象来模拟DOM元素和嵌套关系;
目的:就是为了实现页面元素的高效更新;
- 优点:
1. 减少DOM操作:
以前更新数据的方式:
有1万个节点数据是循环渲染上去的,就要重新渲染1万次,但是其实它可能只有10个数据发生了改变,十分消耗性能
按需加载来更新数据:
虚拟dom可以把多次操作合并为一次操作,比如:以前添加100个节点,只能一个接一个的操作
虚拟dom借助diff算法可以把多余的操作省略,比如:以前100个节点,但其实只有2个新增
2. 跨平台:
虚拟DOM不仅可以变成DOM
还可以变成小程序、iOS应用、安卓应用
因为虚拟DOM本质上只是一个JS对象
- 虚拟DOM长什么样子?
// react中的虚拟dom
const rNode = {
key:null;
props:{
children:[ // 子元素们
{type:"span", ...},
{type:"span", ...},
],
className:"red",// 标签上的属性
onClick:()=>{},// 事件
},
ref:null,
type:"div",// 标签名或组件名
...
}
// vue中的虚拟dom
const vNode = {
type:"div",// 标签名或组件名
data:{
class:"red",// 标签上的属性
on:{
click: ()=>{},// 事件
}
},
children:[ // 子元素们
{type:"span", ...},
{type:"span", ...},
],
...
}
二、Diff算法

Diff算法:虚拟DOM的核心
- 只比较同一层级,不跨级比较
- 标签名不同,直接删除,不继续深度比较
- 标签名相同,key相同,就认为是相同节点,不继续深度比较
1. Tree diff:
将新旧两棵树逐层对比,找出哪些节点需要更亲
如果节点是组件就看:Component diff
如果节点是标签就看:Element diff
2. Component diff:
如果节点是组件,就先看组件类型
类型不同直接替换(删除旧的)
类型相同则只更新属性
3. Element diff:
如果节点是原生标签,则看标签名
标签名不同直接替换,相同则只更新属性
然后进入标签后代做 Tree diff(递归)
- Diff算法缺点: