我有一个使用$(document).ready的脚本,但它不使用jQuery中的任何其他内容。我想通过删除jQuery依赖项来减轻它。
如何在不使用jQuery的情况下实现我自己的$(document).ready功能?我知道,使用window.onload将不同,因为window.onlead在加载所有图像、帧等后启动。
我有一个使用$(document).ready的脚本,但它不使用jQuery中的任何其他内容。我想通过删除jQuery依赖项来减轻它。
如何在不使用jQuery的情况下实现我自己的$(document).ready功能?我知道,使用window.onload将不同,因为window.onlead在加载所有图像、帧等后启动。
当前回答
jQuery中的ready函数做了很多事情。坦率地说,除非你的网站有惊人的小输出,否则我看不出替换它的意义。jQuery是一个非常小的库,它处理您稍后需要的各种跨浏览器的事情。
无论如何,在这里发布它没有什么意义,只需打开jQuery并查看bindReady方法。
它首先根据事件模型调用document.addEventListener(“DOMContentLoaded”)或document.attachEvent(“unreadystatechange”),然后继续。
其他回答
穷人的解决方案:
var checkLoad = function() {
document.readyState !== "complete" ? setTimeout(checkLoad, 11) : alert("loaded!");
};
checkLoad();
查看Fiddle
添加了这个,我想更好一点,自己的范围,非递归
(function(){
var tId = setInterval(function() {
if (document.readyState == "complete") onComplete()
}, 11);
function onComplete(){
clearInterval(tId);
alert("loaded!");
};
})()
查看Fiddle
值得在Rock Solid addEvent()和http://www.braksator.com/how-to-make-your-own-jquery.
这是网站崩溃时的代码
function addEvent(obj, type, fn) {
if (obj.addEventListener) {
obj.addEventListener(type, fn, false);
EventCache.add(obj, type, fn);
}
else if (obj.attachEvent) {
obj["e"+type+fn] = fn;
obj[type+fn] = function() { obj["e"+type+fn]( window.event ); }
obj.attachEvent( "on"+type, obj[type+fn] );
EventCache.add(obj, type, fn);
}
else {
obj["on"+type] = obj["e"+type+fn];
}
}
var EventCache = function(){
var listEvents = [];
return {
listEvents : listEvents,
add : function(node, sEventName, fHandler){
listEvents.push(arguments);
},
flush : function(){
var i, item;
for(i = listEvents.length - 1; i >= 0; i = i - 1){
item = listEvents[i];
if(item[0].removeEventListener){
item[0].removeEventListener(item[1], item[2], item[3]);
};
if(item[1].substring(0, 2) != "on"){
item[1] = "on" + item[1];
};
if(item[0].detachEvent){
item[0].detachEvent(item[1], item[2]);
};
item[0][item[1]] = null;
};
}
};
}();
// Usage
addEvent(window, 'unload', EventCache.flush);
addEvent(window, 'load', function(){alert("I'm ready");});
适用于所有已知的浏览器(通过BrowserStack测试)。IE6+、Safari 1+、Chrome 1+、Opera等。使用DOMContentLoaded,带有document.dococumentElement.doScroll()和window.onload的回退。
/*! https://github.com/Kithraya/DOMContentLoaded v1.2.6 | MIT License */
DOMContentLoaded.version = "1.2.6";
function DOMContentLoaded() { "use strict";
var ael = 'addEventListener', rel = 'removeEventListener', aev = 'attachEvent', dev = 'detachEvent';
var alreadyRun = false, // for use in the idempotent function ready()
funcs = arguments;
// old versions of JS return '[object Object]' for null.
function type(obj) { return (obj === null) ? 'null' : Object.prototype.toString.call(obj).slice(8,-1).toLowerCase() }
function microtime() { return + new Date() }
/* document.readyState === 'complete' reports correctly in every browser I have tested, including IE.
But IE6 to 10 don't return the correct readyState values as per the spec:
readyState is sometimes 'interactive', even when the DOM isn't accessible in IE6/7 so checking for the onreadystatechange event like jQuery does is not optimal
readyState is complete at basically the same time as 'window.onload' (they're functionally equivalent, within a few tenths of a second)
Accessing undefined properties of a defined object (document) will not throw an error (in case readyState is undefined).
*/
// Check for IE < 11 via conditional compilation
/// values: 5?: IE5, 5.5?: IE5.5, 5.6/5.7: IE6/7, 5.8: IE8, 9: IE9, 10: IE10, 11*: (IE11 older doc mode), undefined: IE11 / NOT IE
var jscript_version = Number( new Function("/*@cc_on return @_jscript_version; @*\/")() ) || NaN;
// check if the DOM has already loaded
if (document.readyState === 'complete') { ready(null); return; } // here we send null as the readyTime, since we don't know when the DOM became ready.
if (jscript_version < 9) { doIEScrollCheck(); return; } // For IE<9 poll document.documentElement.doScroll(), no further actions are needed.
/*
Chrome, Edge, Firefox, IE9+, Opera 9+, Safari 3.1+, Android Webview, Chrome for Android, Edge Mobile,
Firefox for Android 4+, Opera for Android, iOS Safari, Samsung Internet, etc, support addEventListener
And IE9+ supports 'DOMContentLoaded'
*/
if (document[ael]) {
document[ael]("DOMContentLoaded", ready, false);
window[ael]("load", ready, false); // fallback to the load event in case addEventListener is supported, but not DOMContentLoaded
} else
if (aev in window) { window[aev]('onload', ready);
/* Old Opera has a default of window.attachEvent being falsy, so we use the in operator instead
https://dev.opera.com/blog/window-event-attachevent-detachevent-script-onreadystatechange/
Honestly if somebody is using a browser so outdated AND obscure (like Opera 7 where neither addEventListener
nor "DOMContLoaded" is supported, they deserve to wait for the full page).
I CBA testing whether readyState === 'interactive' is truly interactive in browsers designed in 2003. I just assume it isn't (like in IE6-8).
*/
} else { // fallback to queue window.onload that will always work
addOnload(ready);
}
// This function allows us to preserve any original window.onload handlers (in super old browsers where this is even necessary),
// while keeping the option to chain onloads, and dequeue them.
function addOnload(fn) { var prev = window.onload; // old window.onload, which could be set by this function, or elsewhere
// we add a function queue list to allow for dequeueing
// addOnload.queue is the queue of functions that we will run when when the DOM is ready
if ( type( addOnload.queue ) !== 'array') { addOnload.queue = [];
if ( type(prev) === 'function') { addOnload.queue.push( prev ); } // add the previously defined event handler
}
if (typeof fn === 'function') { addOnload.queue.push(fn) }
window.onload = function() { // iterate through the queued functions
for (var i = 0; i < addOnload.queue.length; i++) { addOnload.queue[i]() }
};
}
// remove a queued window.onload function from the chain (simplified);
function dequeueOnload(fn) { var q = addOnload.queue, i = 0;
// sort through the queued functions in addOnload.queue until we find `fn`
if (type( q ) === 'array') { // if found, remove from the queue
for (; i < q.length; i++) { ;;(fn === q[i]) ? q.splice(i, 1) : 0; } // void( (fn === q[i]) ? q.splice(i, 1) : 0 )
}
}
function ready(ev) { // idempotent event handler function
if (alreadyRun) {return} alreadyRun = true;
// this time is when the DOM has loaded (or if all else fails, when it was actually possible to inference the DOM has loaded via a 'load' event)
// perhaps this should be `null` if we have to inference readyTime via a 'load' event, but this functionality is better.
var readyTime = microtime();
detach(); // detach any event handlers
// run the functions
for (var i=0; i < funcs.length; i++) { var func = funcs[i];
if (type(func) === 'function') {
func.call(document, { 'readyTime': (ev === null ? null : readyTime), 'funcExecuteTime': microtime() }, func);
// jquery calls 'ready' with `this` being set to document, so we'll do the same.
}
}
}
function detach() {
if (document[rel]) {
document[rel]("DOMContentLoaded", ready); window[rel]("load", ready);
} else
if (dev in window) { window[dev]("onload", ready); }
else {
dequeueOnload(ready);
}
}
function doIEScrollCheck() { // for use in IE < 9 only.
if ( window.frameElement ) {
// we're in an <iframe> or similar
// the document.documentElemeent.doScroll technique does not work if we're not at the top-level (parent document)
try { window.attachEvent("onload", ready); } catch (e) { } // attach to onload if were in an <iframe> in IE as there's no way to tell otherwise
return;
}
try {
document.documentElement.doScroll('left'); // when this statement no longer throws, the DOM is accessible in old IE
} catch(error) {
setTimeout(function() {
(document.readyState === 'complete') ? ready() : doIEScrollCheck();
}, 50);
return;
}
ready();
}
}
用法:
<script>
DOMContentLoaded(function(e) { console.log(e) });
</script>
三个选项:
如果script是主体的最后一个标记,则DOM将在脚本标记执行之前准备就绪当DOM就绪时,“readyState”将变为“complete”将所有内容置于“DOMContentLoaded”事件侦听器下
在准备状态更改时
document.onreadystatechange = function () {
if (document.readyState == "complete") {
// document is ready. Do your stuff here
}
}
来源:MDN
DOMContentLoaded(DOM内容已加载)
document.addEventListener('DOMContentLoaded', function() {
console.log('document is ready. I can sleep now');
});
关注石器时代的浏览器:转到jQuery源代码并使用ready函数。在这种情况下,您不是在解析和执行整个库,您只是在做其中的一小部分。
如果你想支持Internet Explorer 7+(没有怪癖、兼容性和其他问题),最后一个Chrome、最后一个Safari、最后一次Firefox和没有iframes,这就足够了:
is_loaded = false
callbacks = []
loaded = ->
is_loaded = true
for i in [0...callbacks.length]
callbacks[i].call document
callbacks = []
content_loaded = ->
document.removeEventListener "DOMContentLoaded", content_loaded, true
loaded()
state_changed = ->
if document.readyState is "complete"
document.detachEvent "onreadystatechange", state_changed
loaded()
if !!document.addEventListener
document.addEventListener "DOMContentLoaded", content_loaded, true
else
document.attachEvent "onreadystatechange", state_changed
dom_ready = (callback) ->
if is_loaded
callback.call document
else
callbacks.push callback