JavaScript 初始化装载方法

说到 JavaScript 的初始化装载, 可能 onload 是被立刻想到的方法. 但很遗憾, 这是最坏的选择, 我以前也一直犯过这样的错误. 为什么说它不好呢? 因为 onload 不是在 document 加载完成的时候调用的, 而是在页面所有元素 (包括图片等) 全部加载完成才会调用. 也就是说, 如果你的页面上有个尺寸很大的图片, 下载需要很长时间, 那么你的脚本就一直不能被初始化, 直到图片装载完成, 严重影响用户体验.

幸运的是, 在 W3C 中有个叫 DOMContentLoaded 的事件, 故名思意, 它会在 DOM (文档对象模型) 被加载完成的时候触发. 那么我们就可以通过下面的方法调用初始化脚本的方法了.

1
document.addEventListener("DOMContentLoaded", init, false);

但很遗憾, 现在很多浏览器并不玩 W3C 这一套, 支持 DOMContentLoaded 事件的只有 Firefox, Opera 9 等一些 "现代" 浏览器, 而被集成到两大商业桌面系统的 IE 和 Safari 都不支持. 尽管如此, 我们可以用别的一些方法进行处理.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// 如果支持 W3C DOM2, 则使用 W3C 方法
if (document.addEventListener) {
	document.addEventListener("DOMContentLoaded", init, false);
 
// 如果是 IE 浏览器
} else if (/MSIE/i.test(navigator.userAgent)) {
	// 创建一个 script 标签, 该标签有 defer 属性, 当 document 加载完毕时才会被载入
	document.write('<script id="__ie_onload" defer src="javascript:void(0)"></script>');
	var script = document.getElementById("__ie_onload");
	// 如果文档确实装载完毕, 调用初始化方法
	script.onreadystatechange = function() {
		if (this.readyState == 'complete') {
			init();
		}
	}
 
// 如果是 Safari 浏览器
} else if (/WebKit/i.test(navigator.userAgent)) {
	// 创建定时器, 每 0.01 秒检验一次, 如果文档装载完毕则调用初始化方法
	var _timer = setInterval( function() {
		if (/loaded|complete/.test(document.readyState)) {
			clearInterval(_timer);
			init();
		}
	}, 10);
 
// 如果以上皆不是, 使用最坏的方法 (本例中, Opera 7 将会跑到这里来)
} else {
	window.onload = function(e) {
		init();
	}
}

补充一下, JavaScript 中的 defer 属性是 IE 特有的. 它告诉浏览器, 这是一段不需要立即执行的代码, 在文档装载完毕时才被执行. 如果 src 等于 example.js, 那么 example.js 会在文档装载完成后才被装载.

其实绝大多数 JavaScript 框架已经为我们处理好了, 例如 jQuery 的 ready 方法, 只是实现方法不同而已.

用了 JavaScript 有段时间了, 却没有系统的学过, 知识点零零散散的, 所以最近买了本相关的书. 书中谈到了上述问题和解决办法, 我觉得这个方法很实用, 就简单介绍一下. 现在卖个关子, 等我看完这本书再向大家介绍一下书中的内容和知识点.

声明: 本文采用 BY-NC-SA 协议进行授权. 转载请注明转自: JavaScript 初始化装载方法
  1. JAY | #1
    2008-11-16 01:15

    又是沙发哟~
    隐约记得以前貌似给你提到过这个问题的哟~

  2. mg12 | #2
    2008-11-16 01:18

    @JAY
    嗯, 我以前只兼顾了 W3C 和 IE, 觉得有必要拿出来讲讲, 免得忘了. 哈哈~

  3. leojn | #3
    2008-11-16 07:15

    这么早都没抢到沙发

  4. patrick | #4
    2008-11-16 11:17

    "知道图片装载完成",哈哈,发现错别字一个!~~ :smile:
    对精益求精的MG来说这可是比应该的哦! :cool:

  5. mg12 | #5
    2008-11-16 11:56

    @leojn
    没我早...

    @patrick
    更正了, 谢谢!

  6. David | #6
    2008-11-16 12:50

    对了,一直有一个问题。主题样式里似乎没有关于图片的caption的定义,我每次都需要自己去添加。建议check一下

  7. xiaorsz | #7
    2008-11-16 13:20

    什么书哈?呵呵,可以推荐下!!

  8. cool8jay | #8
    2008-11-16 15:04

    莫非是那本很厚很厚的……封面是一只犀牛?

  9. mg12 | #9
    2008-11-16 16:19

    @David
    什么是图片的 Caption?

    @xiaorsz
    好吧, 我承认! 书落在公司并且我忘记书名了, 下周告诉各位.

    @cool8jay
    不是, O'Reilly 的书不太适合我.

  10. 火星人 | #10
    2008-11-16 17:24

    很好很强大。学习了。

  11. bigCat | #11
    2008-11-16 19:38

    jquery确实降低了js门槛,比如ready还有冒泡,哈

  12. mg12 | #12
    2008-11-17 00:25

    @bigCat
    嗯, 这门书也说到冒泡了...

  13. Rowe | #13
    2008-11-17 08:43

    jquery里的ready很好用~ :grin:

  14. David | #14
    2008-11-17 10:43

    @mg12
    例如http://simplife.org/2008/09/16/bankruptcy-of-lehman-and-financial-crisis.html这篇里面,图片下面的文字“雷曼兄弟员工纷纷卷“铺盖”回家”就是caption,wordpress2.6新增加的。

  15. mg12 | #15
    2008-11-17 21:51

    @David
    这个怎么支持? 就是框在一起?
    下次试试吧, 呵呵~

  16. David | #16
    2008-11-18 15:18

    搜到的一篇http://www.digglife.cn/articles/about-wordpress26-image-caption.html,应该就是样式里多加段代码

  17. mg12 | #17
    2008-11-18 20:45

    @David
    好的, 谢谢!

  18. romotc | #18
    2008-11-22 00:47

    研究了半天你上面的RSS Feed的代码,没发现有鼠标时间啊。怎么就能将隐藏的div展现出来的呢?希望指点一下

  19. aobject | #19
    2008-11-22 11:54

    使用setTimeout函数来初始化不好吗

  20. mg12 | #20
    2008-11-22 22:12

    @romotc
    因为我将页面代码和 JavaScript 分离处理了.

    @aobject
    如果你喜欢那样, 当然可以.

  21. romotc | #21
    2008-11-24 21:56

    mg12 :@romotc因为我将页面代码和 JavaScript 分离处理了.
    @aobject如果你喜欢那样, 当然可以.

    但是没发现有onxxx的方法啊。太神奇了...现在你把这个效果给删掉了,没办法研究了

  22. mg12 | #22
    2008-11-25 00:06

    @romotc
    没删除, 我的 Reader Menu 和评论翻页都是用这个实现的.

  23. ShiaoHoo | #23
    2009-03-18 14:22

    window.onload = function() {
    var subbt = document.getElementById("submit");
    subbt.onclick = alert(subbt.nodeType);
    }mg大侠,为什么我用这段实现JS和HTML分离时在onload时候就弹出alert窗口,而不是等onclick事件那,百思不解啊 :cry:

  24. mg12 | #24
    2009-03-18 14:33

    @ShiaoHoo
    一共错了两个地方, 试一下下面的代码:

    1
    2
    3
    4
    5
    6
    7
    
    <input id="submit" type="button" value="Click Here!" />
    <script type="text/javascript">
    	window.onload = function() {
    		var subbt = document.getElementById('submit');
    		subbt.onclick = function() {alert(subbt.nodeType);}
    	}
    </script>
  25. ShiaoHoo | #25
    2009-03-18 21:55

    @mg12
    通过了,哈哈,真太感谢了!!! :grin:

  26. George Wing | #26
    2010-01-03 16:53

    @ShiaoHoo
    这个实现从想法本身而言就错了。为什么要在submit(提交)按钮上去实现click事件?
    form(表单)自身就有个submit事件啊:

    var subbt=document.forms[0].elements['submit'];
    document.forms[0].onsubmit=function(){
    alert(subbt.nodeType)
    };

  27. QiQiBoY | #27
    2010-08-08 23:08

    这段代码有局限性,在IE下。。

  1. JavaScript 的命名空间
    2009-01-07 01:31
  2. 请不要过于依赖 JavaScript
    2009-05-21 00:42
  3. JavaScript页面文档初始化 window.onload的替代办法 - I'm qiqiboy !
    2010-08-08 22:08

Twitter Email feed
RSS feed