原文地址:http://xiaoych.iteye.com/blog/180957 ========================================== load事件可以安全的执行JS,因为该事件是在页面完全加载完后才开始执行(包括页面内的图片、flash等所有元素),不会因为JS需要对某个DOM操作,而页面还没有加载该节点而引起错误。但是这种安全是需要付出代价的:如果某些图片(或者一些别的东西)加载特别慢,那么load事件会等到很久之后才会触发。
针对这个问题,一些JS框架提供了一些补充方法。如:jquery的$(document).ready()、mootools的domready事件。都是在页面的DOM加载完毕后立即执行,而不需要等待漫长的图片下载过程。
如果不使用这些框架,怎样实现自己的 document ready呢?请看以下一段代码:
function __clear(timer){ clearTimeout(timer); clearInterval(timer); return null; };
function __attach_event(evt, callback) { if (window.addEventListener) { window.addEventListener(evt, callback, false); } else if (window.attachEvent) { window.attachEvent("on" + evt, callback); } }
function __domReady(f) { // 假如 DOM 已经加载,马上执行函数 if (__domReady.done) return f(); // 假如我们已经增加了一个函数 if (__domReady.timer) { // 把它加入待执行函数清单中 __domReady.ready.push(f); } else { // 为页面加载完毕绑定一个事件, // 以防它最先完成。使用addEvent(该函数见下一章)。 __attach_event("load", __isDOMReady); // 初始化待执行函数的数组 __domReady.ready = [f]; // 尽可能快地检查DOM是否已可用 __domReady.timer = setInterval(__isDOMReady, 100); } } function __isDOMReady() { // 如果我们能判断出DOM已可用,忽略 if (__domReady.done) return false; // 检查若干函数和元素是否可用 if (document && document.getElementsByTagName && document.getElementById && document.body) { // 如果可用,我们可以停止检查 __clear(__domReady.timer); __domReady.timer = null; // 执行所有正等待的函数 for ( var i = 0; i < __domReady.ready.length; i++ ) { __domReady.ready[i](); } // 记录我们在此已经完成 __domReady.ready = null; __domReady.done = true; } }
具体的调用方法:
__domReady(function() { alert("The dom is loaded!"); });
====================================== 实际测试,证明好使,在图片载入之前就执行了。
其它几个帖子:
DOM Ready 详解 http://www.cnblogs.com/zhangziqiu/archive/2011/06/27/DOMReady.html
http://www.joy-studio.com/frontend-develop/rewrite-javascript-domready-function.html ============================================ mootools的domready.js http://snipplr.com/view/6029/domreadyjs/
/** * domready.js * * Cross browser mozilla's 'onDOMContentLoaded' implementation. * Executes a function when the dom tree is loaded without waiting for images. * * Based on +Element.Events.domready+ from Mootools open source project, * this tiny javascript library adds the emulated 'DOMContentLoaded' functionality. * * Features: * - No dependency on external libraries * - Compatible with Prototype.js * * Tested browsers (Windows): * - IE 7 (XP standalone) * - IE 6 SP2 * - Firefox 2.0.0.4 * - Opera 9.21 * * Tested browsers (Mac OS X): * - Safari 2.0.4 * - Firefox 2.0.0.4 * - Mac Opera 9.21 * - Mac IE 5.2.3 * * Copyright (c) 2007 Takanori Ishikawa. * License: MIT-style license. * * MooTools Copyright: * copyright (c) 2007 Valerio Proietti, <http://mad4milk.net> * * * See Also: * * mootools * http://mootools.net/ * * The window.onload Problem - Solved! * http://dean.edwards.name/weblog/2005/09/busted/ * * [PATCH] Faster onload for Event.onload * http://dev.rubyonrails.org/ticket/5414 * Changeset 6596: Support for "DOMContentLoaded" event handling (prototype.js event branch) * http://dev.rubyonrails.org/changeset/6596 * */ if (typeof Event == 'undefined') Event = new Object(); /* * Registers function +fn+ will be executed when the dom * tree is loaded without waiting for images. * * Example: * * Event.domReady.add(function() { * ... * }); * */ Event.domReady = { add: function(fn) { //----------------------------------------------------------- // Already loaded? //----------------------------------------------------------- if (Event.domReady.loaded) return fn(); //----------------------------------------------------------- // Observers //----------------------------------------------------------- var observers = Event.domReady.observers; if (!observers) observers = Event.domReady.observers = []; // Array#push is not supported by Mac IE 5 observers[observers.length] = fn; //----------------------------------------------------------- // domReady function //----------------------------------------------------------- if (Event.domReady.callback) return; Event.domReady.callback = function() { if (Event.domReady.loaded) return; Event.domReady.loaded = true; if (Event.domReady.timer) { clearInterval(Event.domReady.timer); Event.domReady.timer = null; } var observers = Event.domReady.observers; for (var i = 0, length = observers.length; i < length; i++) { var fn = observers[i]; observers[i] = null; fn(); // make 'this' as window } Event.domReady.callback = Event.domReady.observers = null; }; //----------------------------------------------------------- // Emulates 'onDOMContentLoaded' //----------------------------------------------------------- var ie = !!(window.attachEvent && !window.opera); var webkit = navigator.userAgent.indexOf('AppleWebKit/') > -1; if (document.readyState && webkit) { // Apple WebKit (Safari, OmniWeb, ...) Event.domReady.timer = setInterval(function() { var state = document.readyState; if (state == 'loaded' || state == 'complete') { Event.domReady.callback(); } }, 50); } else if (document.readyState && ie) { // Windows IE var src = (window.location.protocol == 'https:') ? '://0' : 'javascript:void(0)'; document.write( '<script type="text/javascript" defer="defer" src="' + src + '" ' + 'onreadystatechange="if (this.readyState == \'complete\') Event.domReady.callback();"' + '><\/script>'); } else { if (window.addEventListener) { // for Mozilla browsers, Opera 9 document.addEventListener("DOMContentLoaded", Event.domReady.callback, false); // Fail safe window.addEventListener("load", Event.domReady.callback, false); } else if (window.attachEvent) { window.attachEvent('onload', Event.domReady.callback); } else { // Legacy browsers (e.g. Mac IE 5) var fn = window.onload; window.onload = function() { Event.domReady.callback(); if (fn) fn(); } } } } }
|