细说dom就绪事件

标签: dom 事件 | 发表时间:2015-09-04 14:03 | 作者:崔永键
出处:http://www.cuiyongjian.com/

OK,现在来谈谈DOM就绪事件。 这个问题,关系到浏览器内核实现,但我们作为前端,能力不及。便从表象上去理解它,进而推断出对前端开发有所帮助的实践方案,就够了。

 

OK,浏览器DOM加载顺序是什么样的呢?

可以参考IBM的一篇文章:http://www.ibm.com/developerworks/cn/web/1308_caiys_jsload/

据我观察,现代浏览器首先会加载html扫描一遍要下载的资源,开启并行下载,而且这个并行下载并不阻塞浏览器开始执行html。

接下来,浏览器就从头开始执行html,问题来了: 如果执行到js,就阻塞浏览器,阻塞html往下执行,后面的html执行都要等待他下载完并执行完。 而且这个js执行的时候,也会阻塞浏览器那些并行的下载动作。

接下来,html继续往下执行,如果有css会加载并解析css,然后构建DOM,并渲染页面。

直到执行到文件结尾body之前,此时dom结构创建完毕,readystate可能到达了comlete或者lodaed阶段,或者说DOMContentLoaded触发。 此时你便可以干活了,比如绑定dom事件等。  但是页面里面的图片等资源还没加载完,等他们加载完了,就触发window.onload. 

 

那么,如何解决js在头部加载和执行时,对页面造成的阻塞呢?

这个脚本阻塞带来的一个问题就是,用户提前看到白屏。

所以,采用如下方法解决: 

(1)让阻塞发生的晚一点。 怎么办呢。 很明显,把js加载和执行位置挪一挪呗,把它放到页面body结束标签之前。这样阻塞发生的时候,其实页面的所有可见内容已经渲染完了,用户至少看到html和css啦。

(2)让阻塞发生的晚一点,但是操作优雅一点。  当然,让阻塞发生的晚一点,还可以用比较潮流的async和defer加载。 async属性表明这个文件需要异步加载,不会阻塞页面渲染dom操作,避免网页失去响应,但他一旦加载完,很可能就执行了,所以你要思考这个js文件的依赖啥的(万一他去操作dom但dom还没构建完呢,当然dom构建是挺快的)。

      IE不支持async这个属性,只支持defer,所以把defer也写上。 defer是延迟执行,等dom加载完了,再执行这段js。 当然这个js的下载是会异步跟其他资源并行下载的。

(3)比较高大上的解决方式:动态装载脚本,哈哈。 这是目前很多前端模块加载器使用的方法。

使用动态创建script元素来加载,这种方式是用js脚本构建一个script元素,再把它apppend到页面的head里面,这种方式添加的脚本“下载和执行”都不阻断页面渲染,哪怕是添加到head标签在head里面执行,也不会影响页面渲染,所以很适合用。 然后,通过script元素的onload或者onreadyState事件来监听这个脚本有没有加载执行就绪。

其实,这里有个比较严重的问题,就是这种“鸡蛋”总该有个“鸡”来生出来呀。  总该有脚本来装载脚本啊。 所以装载脚本的执行还是会阻塞页面的呀。  故: 前置的装载脚本, 还是得用前面讲到的延迟执行方法

(装载进来的js,浏览器默认就把它执行了。怎么让这种方式加载来的js代码在我想要执行的时候再执行呢,答:学一下AMD等模块加载器的实现,弄一个loader,然后加载js依赖的时候其实加载一个由define函数定义的module,他会把js代码注册到loader里,在依赖他的时候再执行。)

(4)使用xhr对象来下载js脚本内容,然后xhr就绪后,可以在想要运行脚本的时候,往页面中append一个script标签,把脚本文本设置进去。但必须同域。

 

(5)真的使用模块加载器!  使用模块化工具异步加载且保持依赖关系。AMD是提前加载和执行,CMD是用时执行。AMD模块写成commonjs风格的话,其本质上是loader把工厂函数给toString,然后正则匹配出里面的require依赖,给提前加载和执行了。

所以AMD永远是把依赖先加载并执行完了,再执行factory里面的代码。

 AMD好处:提前执行若有错误及时报,不会执行引用模块的代码。  CMD的话可能执行到依赖项的时候,才发现依赖模块执行出错了。 require提前执行的方式就像工厂提前把原材料准备好再干活,干起活来自然不会有卡顿。

相关 [dom 事件] 推荐:

细说dom就绪事件

- - 崔永键的博客
OK,现在来谈谈DOM就绪事件. 这个问题,关系到浏览器内核实现,但我们作为前端,能力不及. 便从表象上去理解它,进而推断出对前端开发有所帮助的实践方案,就够了. OK,浏览器DOM加载顺序是什么样的呢. 可以参考IBM的一篇文章:http://www.ibm.com/developerworks/cn/web/1308_caiys_jsload/.

兼容所有浏览器的 DOM 载入事件

- - Harttle Land
本文就页面载入问题讨论 DOMContentLoaded、 load、 readyState等DOM事件的浏览器兼容性, 并给出怎样绑定DOM载入事件以兼容所有的浏览器. 接着介绍jQuery对该问题的实现源码,以及jQuery中 $(document).ready()和 $(window).load()方法的区别.

样式表的载入会延迟DOM载入事件

- - Harttle Land
绝大多数情况下我们总是让JavaScript在DOM载入后再开始执行. 不管是直接用 DOM API 实现还是使用 jQuery,最终都是 DOMContentLoaded事件在起作用. 本文讨论一个我们习以为常却很少了解的问题: 样式文件的载入会延迟脚本执行,以及 DOMContentLoaded事件的触发.

DOM事件阶段以及事件捕获与事件冒泡先后执行顺序 - AlvinWei

- - 博客园_首页
平时浏览这么多技术文章,如过不去实践、深入弄透它,这个技术点很快就会在脑海里模糊. 重要的事情说三遍,重要的知识写一遍. 开发过程中我们都希望使用别人成熟的框架,因为站在巨人的肩膀上会使得我们开发的效率大幅度提升. 不过,我们也应该、必须了解其基本原理. 比如DOM事件,jquery框架帮我们为我们封装和抽象了各浏览器的差异行为,为事件处理带来了极大的便利.

DOM详解

- - CSDN博客推荐文章
 1.XML解析方式分为两种:dom和sax.   (1)dom:(Document Object Model, 即文档对象模型) 是 W3C 组织推荐的处理 XML 的一种方式.   (2) sax:(Simple API for XML) 不是官方标准,但它是 XML 社区事实上的标准,几乎所有的 XML 解析器都支持它.

javaScript DOM使用

- - CSDN博客互联网推荐文章
通过 HTML DOM,可访问 JavaScript HTML 文档的所有元素. 1 修改HTML元素内容. document.write(Date()); //在输入流中直接写 document.getElementById(id).innerHTML=new HTML. //改变已经有的元素内容 document.getElementById("image").src="landscape.jpg";.

DOM优化

- - JavaScript - Web前端 - ITeye博客
1,Javascript语音与DOM操作就像孤岛. 他们之间的通行是要借助船的,而使用船是有很大成本的. 所以,要先做完一个再做另一个,最好不要交替进行. 如:添加1000个li时,先用一个字符串拼接好,最后一次追加到父节点,而不是向父节点追加1000次,一次追加一个. 如:添加1000个li时,先放到fragment,再添加到UL中.

Android DOM解析XML

- - CSDN博客移动开发推荐文章
if(personChilds.item(y).getNodeType()==Node.ELEMENT_NODE){//判断当前节点是否是元素类型节点. 作者:jaycee110905 发表于2013-2-7 21:04:29 原文链接. 阅读:78 评论:0 查看评论.

jquery和DOM比较

- - JavaScript - Web前端 - ITeye博客
1、window.onload和$(document).ready()的区别. 必须等整个网页中所有的内容加载完毕后(包括图片)才能执行. 网页中所有DOM结构绘制完毕后就执行,可能DOM元素并没有加载完. 2、jquery对象和DOM对象的区别. Juery对象是包装DOM后的产生的对象,DOM是原生对象,是一个基本的文档结构.

Javascript的DOM操作

- - CSDN博客Web前端推荐文章
返回对拥有指定id的第一个对象进行访问. 返回带有指定名称的节点集合. 返回带有指定标签名的对象集合. 返回带有指定class名称的对象集合. 参数:是否复制原节点的所有属性. 注意:IE会忽略节点间生成的空白文本节点(例如,换行符号),而Mozilla不会这样做. 在删除指定节点的时候不会出错,但是如果要删除最后一个子结点或者是第一个子结点的时候,就会出现问题.