DomReady

DomReady

HTML标签和DOM

咱们常常看人们用:javascript

document.getElementById('xxx').style/left = "80px"

结果却报错说找不到元素,可是页面上明明包含id为xxx的这个元素,这实际上就是没分清HTML标签于DOM节点。HTML是一种标记语言,它告诉咱们页面上有什么内容。但行为交互是须要经过DOM操做实现的,不要觉得那两个尖括号的内容就是一个DOM。HTML标签要通过浏览器解析才会变成DOM节点。当咱们向地址栏传入一个URL,开始加载页面,到咱们看到内容,这期间就有一个DOM节点构建的过程。节点们是以树的形式组织的,当页面上全部HTML都转为节点,这就叫作DOM树构建完成,简称之DomReadyhtml

HTML转为为DOM是一个复杂的过程,能够参考这个:HTML TO DOM.java

咱们简单说一下,浏览器是从上到下,从左到右,一个个字符串读入,大体能够认为两个同名的开标签与闭标签就是一个DOM(有的是没有闭签),这时就忽略掉它的两个标签间的内容。页面上有许多标签,但标签会生成一样多的DOM,由于有的标签下只容许存在特定的子标签,好比tr下面必定是td,th, select下面必定是opgroup,option,而option下面,就算你写了<span></span>,它都会忽略掉,option下面只存在文本,这就是咱们须要自定义下拉框的缘故。咱们说过,这顺序是从上到下,有的元素很简单,会构建得很快。但标签存在src,href属性,它会引用外部资源,这就要区别对待了。好比说,script标签,它必定会等src指定的脚本文件加载下来,而后所有执行了里面的脚本,才会分析下一个标签。这种现象叫作堵塞。堵塞是一种很是致命的现象,由于浏览器渲染引擎是单线程的,若是头部脚本过多过大会致使白屏,影响用户体验,所以雅虎的20军规就有一条提到,将全部script标签放到body以后。此外,style标签与link标签,它们在加载样式文件时是不会堵塞,但它们一旦异步加载好,就当即开始渲染已经构建好的元素节点们,这可能会引发重绘,这也影响速度。另外一个影响DOM树构建的所以是iframe,它也会加载资源,虽然不会堵塞DOM构建,但它因为是发出HTTP请求,而HTTP请求是有限,它会与父标签的其余须要加载外部资源的标签产生竞争。咱们常常看到一些新闻网,上面会挂许多iframe广告,这些页面一开始加载时就很卡,也是这缘故。此外还有object元素,用来加载flash等等,这些东西都会影响到DOM树的构建过程。所以在这时候,当咱们贸贸然,使用getElementById,getElementsByTagName获取元素,而后操做它们,就会有很大机率碰到元素为null的异常。这时,目标元素还能够没有转换为DOM节点,还只是一个普通的字符串呢!web

咱们又不能随意写一个浏览器

setTimeout(function(){
   document.getElementById("xxx").style.left = "80px"
}, 3000)

这彻底是靠蒙,可能有效,也可能失败。所以得到全部标签都转换为DOM节点的时机就很是重要。很早期,浏览器提供了一个window.onload方法,但这东西是等到全部标签变成DOM,而且外部资源、图片、背景音乐什么都加载好才触发,时间上有点晚。幸亏,浏览器提供了一个document.readyState属性,当它变成complete时,说明这时机到了。但这是一个属性,不是一个事件,须要使用不太精确的setInterval轮询。如今,W3C终于绅士地提供了一个DOMContentLoaded事件。安全

DOMContentLoaded

DOMContentLoaded应该是最好用的,它是一个事件,表明着虽然stylesheet,images这些资源没有加载好,但HTMLDocument彻底被加载并解析好了,已经能够安全地操做DOM了。ruby

document.addEventListener("DOMContentLoaded", function(event) {
  console.log("DOM fully loaded and parsed");
});

load

load触发的时机是全部的资源所有加载完成,这个时候才操做DOM实际上有点晚了。异步

document.addEventListener("load", function(event) {
    console.log("All resources finished loading!");
  });

readystatechange

// alternative to DOMContentLoaded
document.onreadystatechange = function () {
  if (document.readyState == "interactive") {
      console.log('DOMContentLoaded')
  }
}

//alternative to window.onload
document.onreadystatechange = function(){
  if(document.readyState == "completed"){
    console.log('load')
  }
}

修改自司徒正美的博文,原连接spa

相关文章
相关标签/搜索