当前位置:   article > 正文

关于window.onload加载的多种解决方案_ie window.onload

ie window.onload

转自:http://blog.moocss.com/tutorials/javascript-tutorials/526.html  (Blog也不错,可以看看)

使用JavaScript操纵DOM,必须等待DOM加载完毕才可以执行代码,但window.onload有个坏处,它非要等到页面中的所有图片及视频加载完毕才会触发load事件。结果就是一些本来应该在打开时隐藏起来的元素,由于网络延迟,在页面打开时仍然会出现,然后又会突然消失,让用户觉得莫名其妙。我们想做的就是寻找一种方法来确定DOM被完全的加载时不用等待所有那些讨厌的图片加载完毕。必须与这种丑陋的闪烁告别!

我这里整理出针对onload事件的七种方案。

第七种方案是我们最终的解决方案,也是完美的解决方案。

三 ~ 六 的解决方案只解决了window.onload加载多个方法,但是还没有解决图片的等待加载问题,还有它们只兼容IE和FF。

最成熟的解决:http://javascript.nwbox.com/ContentLoaded/

定义和用法 
onload 事件会在页面或图像加载完成后立即发生。

语法

οnlοad=”SomeJavaScriptCode”

支持该事件的 HTML 标签:

1
<body>, <frame>, <frameset>, <iframe>, <img>, <link>, <script>

支持该事件的 JavaScript 对象:

image, layer, window实例

第一种:

1
2
3
  1. function loadFunction(){
  2. alert("hello!");
  3. }

 

1
<body onload="loadFunction()">

 

第二种:

1
2
3
4
  1. window.onload = loadFunction;
  2. function loadFunction(){
  3. alert("hello!");
  4. }

 

第三种:

1
2
3
4
5
6
7
8
9
10
11
  1. function firstFunction(){
  2. alert("hello firstFun !");
  3. }
  4. function secondFunction(){
  5. alert("hello secondFun !");
  6.  
  7. }
  8. window.onload = function(){
  9. firstFunction();
  10. secondFunction();
  11. }

 

第四种:通用的做法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
  1. function firstFunction(){
  2. alert("hello firstFun !");
  3. }
  4. function secondFunction(){
  5. alert("hello secondFun !");
  6.  
  7. }
  8.  
  9. function addLoadEvent(func) {
  10. var oldonload = window.onload;
  11. if (typeof window.onload != 'function') {
  12. window.onload = func;
  13. } else {
  14. window.onload = function() {
  15. oldonload();
  16. func();
  17. }
  18. }
  19. }
  20.  
  21. //测试
  22. addLoadEvent(firstFunction);
  23. addLoadEvent(secondFunction);

addLoadEvent工作流程:

把现有的window.onload事件处理函数的值存入变量oldonload。

如果在这个处理函数上还没有绑定任何函数,就像平时那样把新函数添加给它;

如果在这个处理函数已经绑定了一些函数,就把函数追回到现有指令未尾。

浏览器加载html内容是自上而下的(默认),而JS一般是在哪里引入——想想如果JS里面包含了一些即时执行指令,

它会操作根本不存在元素节点(因为还没有加载完)会有什么后果?结果就是出错。

addLoadEvent可以实现无论有多少个函数,都能让它们同时和window.onload事件绑定。

第五种; 推荐

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
  1. function a(){
  2. alert("a");
  3. }
  4.  
  5. function b(){
  6. alert("b");
  7. }
  8.  
  9.  
  10. function addEvent(obj,EventName,callBack){//给对象添加事件
  11. if(obj.addEventListener){ //FF
  12. obj.addEventListener(EventName,callBack,false);
  13. }else if(obj.attachEvent){//IE
  14. obj.attachEvent('on'+EventName,callBack);
  15. }else{
  16. obj["on"+EventName]=callBack;
  17. }
  18. }
  19. //测试
  20. addEvent(window,"load",a);
  21. addEvent(window,"load",b);

 

第六种:推荐

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
33
34
35
36
37
38
39
40
41
42
43
44
  1. function a(){
  2. alert("a");
  3. }
  4.  
  5. function b(){
  6. alert("b");
  7. }
  8. // Please note: this file contains snippets for comparison
  9. // it is not self-contained or ready-to-use code as such
  10. function addLoadListener(fn)
  11. {
  12. if (typeof window.addEventListener != 'undefined')
  13. {
  14. window.addEventListener('load', fn, false);
  15. }
  16. else if (typeof document.addEventListener != 'undefined')
  17. {
  18. document.addEventListener('load', fn, false);
  19. }
  20. else if (typeof window.attachEvent != 'undefined')
  21. {
  22. window.attachEvent('onload', fn);
  23. }
  24. else
  25. {
  26. var oldfn = window.onload;
  27. if (typeof window.onload != 'function')
  28. {
  29. window.onload = fn;
  30. }
  31. else
  32. {
  33. window.onload = function()
  34. {
  35. oldfn();
  36. fn();
  37. };
  38. }
  39. }
  40. }
  41.  
  42. //测试
  43. addLoadListener(a);
  44. addLoadListener(b);

 

第七种:最完美的解决方案

建立一个独立的通用解决方案,兼容各种浏览器,任何人都可以使用,而无需一个具体的框架。

最初的完整解决方案:http://dean.edwards.name/weblog/2006/06/again/

一个独立的通用解决方案 :http://www.thefutureoftheweb.com/blog/adddomloadevent.

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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
  1.  
  2. /*
  3. * (c)2006 Jesse Skinner/Dean Edwards/Matthias Miller/John Resig
  4. * Special thanks to Dan Webb's domready.js Prototype extension
  5. * and Simon Willison's addLoadEvent
  6. *
  7. * For more info, see:
  8. * http://www.thefutureoftheweb.com/blog/adddomloadevent
  9. * http://dean.edwards.name/weblog/2006/06/again/
  10. * http://www.vivabit.com/bollocks/2006/06/21/a-dom-ready-extension-for-prototype
  11. * http://simon.incutio.com/archive/2004/05/26/addLoadEvent
  12. *
  13. *
  14. * To use: call addDOMLoadEvent one or more times with functions, ie:
  15.  
  16. * addDOMLoadEvent的调用方法,如下:
  17. * function something() {
  18. * // do something
  19. * }
  20. * addDOMLoadEvent(something);
  21. *
  22. * addDOMLoadEvent(function() {
  23. * // do other stuff
  24. * });
  25. *
  26. */
  27.  
  28. addDOMLoadEvent = (function(){
  29.  
  30. // create event function stack
  31. var load_events = [],
  32. load_timer,
  33. script,
  34. done,
  35. exec,
  36. old_onload,
  37. init = function () {
  38. done = true;
  39. /*//停止调用计时器*/
  40. // kill the timer
  41. clearInterval(load_timer);
  42.  
  43. // execute each function in the stack in the order they were added
  44. while (exec = load_events.shift())
  45. exec();
  46.  
  47. if (script) script.onreadystatechange = '';
  48. };
  49.  
  50. return function (func) {
  51. // if the init function was already ran, just run this function now and stop
  52. if (done) return func();
  53.  
  54. if (!load_events[0]) {
  55.  
  56. // for Mozilla/Opera9
  57. /*
  58. DOMContentLoaded是firefox下特有的Event, 当所有DOM解析完以后会触发这个事件。
  59. 注册DOMContentLoaded事件,如果支持的话
  60. */
  61. if (document.addEventListener)
  62. document.addEventListener("DOMContentLoaded", init, false);
  63.  
  64. // for Internet Explorer
  65. /*
  66. 对于IE则使用条件注释,并使用script标签的defer属性
  67. IE中可以给script标签添加一个defer(延迟)属性,这样,标签中的脚本只有当DOM加载完毕后才执行*/
  68.  
  69. /*@cc_on @*/
  70. /*@if (@_win32)
  71. document.write("<script id=__ie_onload defer src=//0><\/scr"+"ipt>");
  72. script = document.getElementById("__ie_onload");
  73. script.onreadystatechange = function() {
  74. if (this.readyState == "complete")
  75. init(); // call the onload handler
  76. };
  77. /*@end @*/
  78.  
  79. // for Safari
  80. /*
  81. 但对于Safari,我们需要使用setInterval方法不断检测document.readyState
  82. 当为loaded或complete的时候表明DOM已经加载完毕
  83. */
  84.  
  85. if (/WebKit/i.test(navigator.userAgent)) { // sniff
  86. load_timer = setInterval(function() {
  87. if (/loaded|complete/.test(document.readyState))
  88. init(); // call the onload handler
  89. }, 10);
  90. }
  91.  
  92. // for other browsers set the window.onload, but also execute the old window.onload
  93. old_onload = window.onload;
  94. window.onload = function() {
  95. init();
  96. if (old_onload) old_onload();
  97. };
  98. }
  99.  
  100. load_events.push(func);
  101. }
  102. })();

 

方案七的演示:

 

最成熟的解决方案:

第七种方案回头看,源码中的 hacks 用的太多,也并不完美,接下来,就看一个大家都在用的:

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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
  1. /*!
  2. * contentloaded.js
  3. *
  4. * Author: Diego Perini (diego.perini at gmail.com)
  5. * Summary: cross-browser wrapper for DOMContentLoaded
  6. * Updated: 20101020
  7. * License: MIT
  8. * Version: 1.2
  9. *
  10. * URL:
  11. * http://javascript.nwbox.com/ContentLoaded/
  12. * http://javascript.nwbox.com/ContentLoaded/MIT-LICENSE
  13. *
  14. */
  15.  
  16. // @win window reference
  17. // @fn function reference
  18. (function(win, doc) {
  19. contentLoaded=function(fn) {
  20. var done = false, top = true,
  21.  
  22. doc = win.document, root = doc.documentElement,
  23.  
  24. add = doc.addEventListener ? 'addEventListener' : 'attachEvent',
  25. rem = doc.addEventListener ? 'removeEventListener' : 'detachEvent',
  26. pre = doc.addEventListener ? '' : 'on',
  27.  
  28. init = function(e) {
  29. if (e.type == 'readystatechange' && doc.readyState != 'complete') return;
  30. (e.type == 'load' ? win : doc)[rem](pre + e.type, init, false);
  31. if (!done && (done = true)) fn.call(win, e.type || e);
  32. },
  33.  
  34. poll = function() {
  35. try { root.doScroll('left'); } catch(e) { setTimeout(poll, 50); return; }
  36. init('poll');
  37. };
  38.  
  39. if (doc.readyState == 'complete') fn.call(win, 'lazy');
  40. else {
  41. if (doc.createEventObject && root.doScroll) {
  42. try { top = !win.frameElement; } catch(e) { }
  43. if (top) poll();
  44. }
  45. doc[add](pre + 'DOMContentLoaded', init, false);
  46. doc[add](pre + 'readystatechange', init, false);
  47. win[add](pre + 'load', init, false);
  48. }
  49.  
  50. }
  51. })(window, document);
  52. <pre>
  53. <h3>使用方法:</h3>
  54. <pre lang="javascript" line="1">
  55. //测试
  56. var $tt = (new Date).getTime();
  57. function timeElapsed(t) { return ((new Date()).getTime() - t); }
  58. contentLoaded(
  59. function (e) {
  60. document.body.style.backgroundColor = 'green';
  61. window.status =
  62. window.defaultStatus =
  63. ' * ' + (e.type || e) + ' ' +
  64. ' - ' + (e.eventType ? e.eventType : 'native') +
  65. ' in ' + timeElapsed($tt) + ' ms.';
  66. }
  67. );
  68.  
  69. //测试
  70. contentLoaded(
  71. function(){
  72. var el=document.getElementById('logo');
  73. console.log(el);
  74. }
  75. );
This entry was posted in  JavaScript and tagged Tags:  JavaScriptJavaScript基础. Bookmark the permalink

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/神奇cpp/article/detail/898897
推荐阅读
相关标签
  

闽ICP备14008679号