原生domReady封装
核心思路:
标准浏览器(含IE9+)比较简单,直接监听DOMContentLoaded事件;
低版本的IE(IE678)两套机制:
1)尝试轮询document.documentElement.doScroll("left")是否报错,若报错则dom树结构未ready,否则dom ready;
2)监听document的onreadystatechange事件,判断document.readyState是否为"complete"。
参考:http://javascript.nwbox.com/IEContentLoaded/
直接上源码了:
var domReady = (function () { var doc = document, branch = document.addEventListener ? 'w3c' : 'ie678'; var _domReady = { // When _domReady.done is true,all 'fn' will be invoked immediately. done: false, // The stack which all functions will be pushed into fn: [], // push callback functions push: function (fn) { if (!_domReady.done) { // only bind once if (_domReady.fn.length === 0) { _domReady.bind(); } _domReady.fn.push(fn); } else { fn(); } }, // The Real DOMContentLoaded Callback Function ready: function () { // Flag DOMContentLoaded Event was Done over _domReady.done = true; var fn = _domReady.fn; for (var i = 0, l = fn.length; i < l; i++) { fn[i](); } _domReady.unbind(); _domReady.fn = null; }, bind: { w3c: function () { doc.addEventListener('DOMContentLoaded', _domReady.ready, false); }, //IE的监听 ie678: function () { var done = false, // only fire once init = function () { if (!done) { done = true; _domReady.ready(); } }; // polling for no errors (function () { try { // throws errors until after ondocumentready doc.documentElement.doScroll('left'); } catch (e) { setTimeout(arguments.callee, 20); return; } // no errors, fire init(); })(); // trying to always fire before onload doc.onreadystatechange = function () { if (doc.readyState == 'complete') { doc.onreadystatechange = null; init(); } }; } }[branch], unbind: { w3c: function () { doc.removeEventListener('DOMContentLoaded', _domReady.ready, false); }, ie678: function () { /* Nothing to do */ } }[branch] }; return _domReady.push; })();
使用方法:
可以尝试跟window.onload做个比较
window.onload = function(){ alert("onload"); }; domReady(function(){ alert("domReady 1"); }); domReady(function(){ alert("domReady 2"); });