要明白diff算法,还是要从dom说起。
dom
什么是dom?
全称:Document Object Model(文档对象模型)
是网页用来表示文档中对象的标准模型,是针对HTML和XML的API。
浏览器生成DOM过程
浏览器的主要组件?
用户界面:UI布局,比如地址栏前后退,收藏夹
浏览器引擎:在用户界面和渲染引擎之间传递指令,同时操作数据存储
渲染引擎:主要负责将请求的布局文件、样式文件进行解析渲染,呈现出web页面。
网络:进行HTTP请求调用。
js解释器:负责解析并执行JavaScript语言。
从输入一个url到返回页面的过程发生了什么?
HTTP过程:
1.在地址栏输入URL,浏览器先查看浏览器缓存-系统缓存-路由器缓存,如果缓存中有,会直接在屏幕中显示页面内容。若没有,进行下一步
2.浏览器对输入的URL进行域名解析,获取相应的IP地址
3.浏览器向URL所在的服务器发起tcp请求,建立三次握手
4.握手成功后,浏览器向服务器发送HTTP请求,请求数据
5.服务器响应请求,将数据返回至浏览器。
6.浏览器收到响应,解析html,渲染页面
浏览器渲染过程:
1.构建dom树:浏览器会把获取到的html文档解析成一个dom树,html中的每个标签都是dom树的节点。(DOM树里包含了所有HTML标签,包括display:none隐藏,还有用JS动态添加的元素等)
2.构建cssom树:浏览器会把所有样式解析成样式结构体。(在解析的过程中会去掉浏览器不能识别的样式,比如IE会去掉-moz开头的样式,而FF会去掉_开头的样式)
3.将 DOM 与 CSSOM 合并成一个渲染树。
render tree类似于DOM tree,但区别很大,render tree能识别样式,render tree中每个节点都有自己的样式,而且 render tree不包含隐藏的节点 (比如display:none的节点,还有head节点)因为这些节点不会用于呈现,而且不会影响呈现的,所以就不会包含到 render tree中。注意 visibility:hidden隐藏的元素还是会包含到 render tree中的,因为visibility:hidden 会影响布局,会占有空间。根据CSS2的标准,render tree中的每个节点都称为Box ,理解页面元素为一个具有填充、边距、边框和位置的盒子。
4.布局:浏览器开始布局,为每个渲染树的节点确定一个在显示屏上出现的精确坐标。
5.绘制:Render树和节点显示坐标都有了,就调用每个节点paint方法,把它们绘制出来。
html的解析,遵循以下规则:1.按顺序解析,从上到下。2.link标签的加载阻塞后续代码执行,但不影响外部文件(link,script,可以同时加载。)3.添加async属性的script,异步加载,不会被阻塞,但可能读取dom节点失败
引申提问:
什么是回流?什么是重绘?
回流(重排 reflow):当修改DOM或修改元素的形状大小,浏览器部分或者全部重新渲染的过程。
重绘(repaint):修改dom元素的样式,浏览器不需要重新计算元素的几何属性,直接可以为该元素绘制新的样式,这个过程叫重绘。
哪些事件导致重排(回流)?
添加或删除可见的dom元素
元素的位置发生变化
元素的尺寸发生变化
内容改变(比如文本或者图片改变引起高度宽度重新计算)
缩放浏览器窗口,浏览器窗口尺寸改变。
HTML页面首次初始化呈现。
最复杂的一种:获取某些属性,引发回流
如何避免重排(回流)?
避免频繁操作dom
避免使用table布局
让元素脱离文档流,减少渲染树的规模
尽可能的使用className
虚拟dom
什么是虚拟dom?
虚拟dom就是将真实的节点dom用js模拟出来。
为什么要使用虚拟dom?
首先,一个dom节点是很庞大的,它有很多属性,每次操作dom是一个相当耗时的过程。
第二,当更新一个dom节点的时候,很有可能会触发回流操作,导致浏览器会重新渲染部分或全部文档。
(打个比方,你有一个PPT,老板要你改几个字,你会重新去写一份PPT么?)
第三,当对多个dom进行更新的时候,每一次都要重新计算dom节点的坐标信息,会造成性能的浪费。
而虚拟dom就很好的解决了上述问题,当我们执行更新大量节点的操作时,可以通过虚拟dom找出最小的变化,然后再把这些改动写入实际的dom中,虚拟dom减少了实际操作dom的次数,有利于性能提升。
vue2中的diff算法是怎样实现的?
什么是diff算法?
Vue通过编译将模板转换AST,之后将AST转换成渲染函数,执行渲染函数可以得到一个虚拟节点树(vnode),再拿新生成的虚拟节点树去和旧的虚拟节点树(oldVnode)对比,找出更新部分节点,最后做渲染。
vnode与oldVnode对比的过程,也就是常说的diff算法。
diff算法