浏览器中的Dom
文档对象模型Dom是独立于语言的,用以操作XML和HTML文档的程序接口(API)。在浏览器中的接口通常是以javascript操作的,因此大多数的脚本都在与DOM打交道。Dom和javascript两个接口是独立存在的。因此如果通过功能接口连接,就会产生较大的性能损害,连接的次数越多,对性能的损害就越大。
Dom的修改和访问
访问一次Dom,就会产生一定性能上的损失,修改Dom在性能上的损失更大。因为会导致浏览器重新计算页面的几何变化。
innerHtml和Dom方法的比较:如果不考虑标准的问题,他们的性能上差别不大。但是在所有浏览器中innerHtml的速度要快的很多,除了基于webkit的(Chrome和safari)。
!!使用节点克隆代替creatElment();
Html集合:Html集合是一个类似数组的存放html元素的列表,常用的获取Html集合有以下几种方法(说实话用惯了框架在回头看这些原生的东西真的有些陌生):
document.getElementById:
document.getElementsByTagName:
document.getElementsByClassName:(不支持IE8及IE8以下)
document.images
document.links
document.forms
这些方法返回的html collection对象是一个类似于数组的列表。他没有数组的一些方法(push(),slice())等,但是通过.length可以返回这个列表的长度,通过索引值也可以获取这个列表中的第N项。
HTML集合实际上是在查询文档,当你更新时,每次都会重复这个查询操作,例如返回这个集合的长度,这是一个非常低效率的方法。遍历同样大小和内容的数组和html集合,遍历数组的速度明显较快。
!!解决办法:
- 将HTML集合拷贝到一个数组中,通过遍历数组
- 在每次迭代的访问集合的长度的时候,都会导致集合更新,在浏览器中会导致性能的损失。可以将长度缓存在变量中
- 在迭代访问的时候使用局部变量
抓取Dom
1.在新版本的浏览器中两个方法的抓取速度差不多,但是老式的IE浏览器中,nexsibling的速度要比childNodes的速度要快。
2.使用children来代替childNodes
3.选择器API,根据CSS选择器查询特定元素,比如document.querySelector()和querySelectorAll(),这两个方法都是DOM节点的方法,因此支持子查询。返回NodeList(包含匹配节点的类数组对象),NodeList对象是一个静态列表,不会对应实时的文档结构。
document.querySelector()//返回符合规则的第一个节点
querySelectorAll()//返回符合规则的所有节点
重绘和重排版
当浏览器下载并解析完HTML标记文件的Dom,Css,图片,javascript之后,会生成两个内部的数据结构:
- Dom树(HTML的标签结构)
渲染树 为每个Dom树上每个需要显示的节点分配一个内存,(隐藏的Dom节点不会分配内存),节点树上的节点称为“框”,“盒”。一旦Dom树和渲染树构造完毕,浏览器就可以显示这些元素了。
当DOM改变影响到元素的几何高度和宽度时原有的渲染树中受影响的部分的部分将失效,渲染树进行重构,这个过程叫做重排版,经过一系列的渲染之后,浏览器在重绘进程中将渲染树显示到浏览器,这个过程叫做重绘。这些过程是及其损害浏览器的性能的。//之后改变盒模型时才会进行重绘
下面的几种情况会导致网页重排版:
- 添加或者删除可见的dom元素
- 元素位置发生改变
- 元素的盒模型改变
- 内容改变
- 浏览器窗口改变
当通过以上条件查询并返回最新的值时,网页会进行重排版:
优化原则:最小化重绘和重排
合并操作
el.style.borderLeft = “1px”;
el.style.borderRight = “2px”;
el.style.padding = “5px”;
可以优化为:
el.style.cssText = “border-left:1px;border-right:2px;padding:5px;”
批量修改
将需要修改的dom从浏览器中脱离(定位),进行多重修改,在放回文档流
三种方法:
- 隐藏元素,进行修改,显示元素
- 将原始文本复制到一个脱离文档的文本,进行操作在覆盖原有的
- 使用绝对定位(但是会覆盖下面的元素)