var a = { name: 'A' }
not var a = new Object(); a.name = 'A'
文档对象模型是一个独立于语言的,用于操作xml 和 html文档的程序接口API。 在浏览器中,用来与HTML文档打交道,同样也用在web程序中获取xml文档,并且使用DOM API来访问文档中的数据。
DOM是个与语言无关的API,它在浏览器中的接口是用javascript实现的。
浏览器将【DOM与渲染】 和 javascript部分独立实现。比如chrome渲染引擎就是基于webkit的blink,javascript引擎是V8.
因为两个独立的功能通过接口连接,就会产生消耗,比如建立http连接的A和B必然会有消耗,访问DOM的次数过多,建立连接的过程就会增多,成本就越高。
浏览器在下载完所有的页面组件之后会解析生成两个内部数据结构,一个DOM树,一个 CSSOM树;最后生成渲染树-然后渲染页面
DOM描述了页面元素的结构,CSSOM描述了页面元素的样式。
当DOM的变化影响了元素的几何属性(宽、高、在页面中的坐标),浏览器需要重新计算该元素的几何属性,并且其他元素的几何属性和位置也会被受到影响,CSSOM中的收到影响的部分失效,并且重新构造CSSOM 树- 最后重新构造渲染树。 这个过程为重排。 完成重排之后,浏览器会根据最新的渲染树绘制受影响的部分到屏幕中,这个过程成为重绘。
并不是所有的DOM变化都会影响元素的几何属性,比如改变一个元素的背景颜色并不会影响它的宽和高,只会有一次重绘。
元素几何属性变化以及页面布局变化就需要重排。
由于每次重排会产生计算消耗,大多数浏览器通过==队列化(变化先入队,队列满了,改变然后下一个开始)==修改来优化重排过程。但是你可能无意间会触发队列强制更新。比如下面的
offsetTop, offsetLeft, offsetWidth, offsetHeight
scrollTop, scrollLeft,scrollWidth, scrollHeight
clientTop, clientLeft, clientWidth, clientHeight
getComputedStyle()
这些API需要返回最新的布局信息,这时候浏览器必须执行渲染队列中的“待处理变化”,必须强制刷新渲染队列中,即将变化但是还没有变化的操作。
所以在布局信息变化的时候,尽量不要上面的API去查询数据。
合并多次对dom和样式的修改,然后一次性处理掉。
多次样式操作合并到一个文本字符串里面,或者放在一个class里面,然后一次性。使用element.style.cssText
或者 element.className
而不是element.style.xxx
具体的多次改变。
当在一些特定的情况下,我们必须要改变元素的几何属性,这个时候避免不了。只能尽量减少重排。
这时候推荐的做法是:
第1步和第3步会触发重排,如果第2步的操作减少了很多次,那么这个过册过程总体还是优的。
使元素脱离文档流,有3种方式:
document.createDocumentFragment()
【最优,重排次数最少】ELEMENT.cloneNode(true)
给动画元素设置绝对布局,脱离文档流,动画结束的时候恢复,和上面离线操作dom ,缓存数据,减少布局的变化影响文档流
绑定事件到父亲节点或者外层元素,它基于: 事件逐层冒泡并能被父级元素捕获。
其实现在大都使用几个框架,可能有的不太能直接适用,但是可以给我们在优化上提供很多思路!
资料:
《高性能javascript》第二章
W3C-DOM
MDN-DOM