我有一个使用$(document).ready
的脚本,但它不使用jQuery中的任何其他内容。我想通过删除jQuery依赖来减轻它。
如何在不使用jQuery的情况下实现自己的$(document).ready
功能?我知道使用window.onload
将不一样,因为window.onload
在所有图像,帧等加载后都会触发。
答案 0 :(得分:1243)
基于标准的替换DOMContentLoaded
得到98% of browsers的支持,但不是IE8:
document.addEventListener("DOMContentLoaded", function(event) {
//do work
});
jQuery的本机函数比window.onload复杂得多,如下所示。
function bindReady(){
if ( readyBound ) return;
readyBound = true;
// Mozilla, Opera and webkit nightlies currently support this event
if ( document.addEventListener ) {
// Use the handy event callback
document.addEventListener( "DOMContentLoaded", function(){
document.removeEventListener( "DOMContentLoaded", arguments.callee, false );
jQuery.ready();
}, false );
// If IE event model is used
} else if ( document.attachEvent ) {
// ensure firing before onload,
// maybe late but safe also for iframes
document.attachEvent("onreadystatechange", function(){
if ( document.readyState === "complete" ) {
document.detachEvent( "onreadystatechange", arguments.callee );
jQuery.ready();
}
});
// If IE and not an iframe
// continually check to see if the document is ready
if ( document.documentElement.doScroll && window == window.top ) (function(){
if ( jQuery.isReady ) return;
try {
// If IE is used, use the trick by Diego Perini
// http://javascript.nwbox.com/IEContentLoaded/
document.documentElement.doScroll("left");
} catch( error ) {
setTimeout( arguments.callee, 0 );
return;
}
// and execute any waiting functions
jQuery.ready();
})();
}
// A fallback to window.onload, that will always work
jQuery.event.add( window, "load", jQuery.ready );
}
答案 1 :(得分:318)
编辑:
function ready(callback){
// in case the document is already rendered
if (document.readyState!='loading') callback();
// modern browsers
else if (document.addEventListener) document.addEventListener('DOMContentLoaded', callback);
// IE <= 8
else document.attachEvent('onreadystatechange', function(){
if (document.readyState=='complete') callback();
});
}
ready(function(){
// do something
});
取自 https://plainjs.com/javascript/events/running-code-when-the-document-is-ready-15/
Another good domReady function here取自https://stackoverflow.com/a/9899701/175071
由于接受的答案还远未完成,我根据jQuery 1.6.2源码拼凑了一个“就绪”函数,如jQuery.ready()
:
var ready = (function(){
var readyList,
DOMContentLoaded,
class2type = {};
class2type["[object Boolean]"] = "boolean";
class2type["[object Number]"] = "number";
class2type["[object String]"] = "string";
class2type["[object Function]"] = "function";
class2type["[object Array]"] = "array";
class2type["[object Date]"] = "date";
class2type["[object RegExp]"] = "regexp";
class2type["[object Object]"] = "object";
var ReadyObj = {
// Is the DOM ready to be used? Set to true once it occurs.
isReady: false,
// A counter to track how many items to wait for before
// the ready event fires. See #6781
readyWait: 1,
// Hold (or release) the ready event
holdReady: function( hold ) {
if ( hold ) {
ReadyObj.readyWait++;
} else {
ReadyObj.ready( true );
}
},
// Handle when the DOM is ready
ready: function( wait ) {
// Either a released hold or an DOMready/load event and not yet ready
if ( (wait === true && !--ReadyObj.readyWait) || (wait !== true && !ReadyObj.isReady) ) {
// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
if ( !document.body ) {
return setTimeout( ReadyObj.ready, 1 );
}
// Remember that the DOM is ready
ReadyObj.isReady = true;
// If a normal DOM Ready event fired, decrement, and wait if need be
if ( wait !== true && --ReadyObj.readyWait > 0 ) {
return;
}
// If there are functions bound, to execute
readyList.resolveWith( document, [ ReadyObj ] );
// Trigger any bound ready events
//if ( ReadyObj.fn.trigger ) {
// ReadyObj( document ).trigger( "ready" ).unbind( "ready" );
//}
}
},
bindReady: function() {
if ( readyList ) {
return;
}
readyList = ReadyObj._Deferred();
// Catch cases where $(document).ready() is called after the
// browser event has already occurred.
if ( document.readyState === "complete" ) {
// Handle it asynchronously to allow scripts the opportunity to delay ready
return setTimeout( ReadyObj.ready, 1 );
}
// Mozilla, Opera and webkit nightlies currently support this event
if ( document.addEventListener ) {
// Use the handy event callback
document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
// A fallback to window.onload, that will always work
window.addEventListener( "load", ReadyObj.ready, false );
// If IE event model is used
} else if ( document.attachEvent ) {
// ensure firing before onload,
// maybe late but safe also for iframes
document.attachEvent( "onreadystatechange", DOMContentLoaded );
// A fallback to window.onload, that will always work
window.attachEvent( "onload", ReadyObj.ready );
// If IE and not a frame
// continually check to see if the document is ready
var toplevel = false;
try {
toplevel = window.frameElement == null;
} catch(e) {}
if ( document.documentElement.doScroll && toplevel ) {
doScrollCheck();
}
}
},
_Deferred: function() {
var // callbacks list
callbacks = [],
// stored [ context , args ]
fired,
// to avoid firing when already doing so
firing,
// flag to know if the deferred has been cancelled
cancelled,
// the deferred itself
deferred = {
// done( f1, f2, ...)
done: function() {
if ( !cancelled ) {
var args = arguments,
i,
length,
elem,
type,
_fired;
if ( fired ) {
_fired = fired;
fired = 0;
}
for ( i = 0, length = args.length; i < length; i++ ) {
elem = args[ i ];
type = ReadyObj.type( elem );
if ( type === "array" ) {
deferred.done.apply( deferred, elem );
} else if ( type === "function" ) {
callbacks.push( elem );
}
}
if ( _fired ) {
deferred.resolveWith( _fired[ 0 ], _fired[ 1 ] );
}
}
return this;
},
// resolve with given context and args
resolveWith: function( context, args ) {
if ( !cancelled && !fired && !firing ) {
// make sure args are available (#8421)
args = args || [];
firing = 1;
try {
while( callbacks[ 0 ] ) {
callbacks.shift().apply( context, args );//shifts a callback, and applies it to document
}
}
finally {
fired = [ context, args ];
firing = 0;
}
}
return this;
},
// resolve with this as context and given arguments
resolve: function() {
deferred.resolveWith( this, arguments );
return this;
},
// Has this deferred been resolved?
isResolved: function() {
return !!( firing || fired );
},
// Cancel
cancel: function() {
cancelled = 1;
callbacks = [];
return this;
}
};
return deferred;
},
type: function( obj ) {
return obj == null ?
String( obj ) :
class2type[ Object.prototype.toString.call(obj) ] || "object";
}
}
// The DOM ready check for Internet Explorer
function doScrollCheck() {
if ( ReadyObj.isReady ) {
return;
}
try {
// If IE is used, use the trick by Diego Perini
// http://javascript.nwbox.com/IEContentLoaded/
document.documentElement.doScroll("left");
} catch(e) {
setTimeout( doScrollCheck, 1 );
return;
}
// and execute any waiting functions
ReadyObj.ready();
}
// Cleanup functions for the document ready method
if ( document.addEventListener ) {
DOMContentLoaded = function() {
document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
ReadyObj.ready();
};
} else if ( document.attachEvent ) {
DOMContentLoaded = function() {
// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
if ( document.readyState === "complete" ) {
document.detachEvent( "onreadystatechange", DOMContentLoaded );
ReadyObj.ready();
}
};
}
function ready( fn ) {
// Attach the listeners
ReadyObj.bindReady();
var type = ReadyObj.type( fn );
// Add the callback
readyList.done( fn );//readyList is result of _Deferred()
}
return ready;
})();
使用方法:
<script>
ready(function(){
alert('It works!');
});
ready(function(){
alert('Also works!');
});
</script>
我不确定这段代码的功能如何,但它在我的肤浅测试中运行良好。这花了很长时间,所以我希望你和其他人可以从中受益。
PS:我建议compiling。
或者您可以使用http://dustindiaz.com/smallest-domready-ever:
function r(f){/in/.test(document.readyState)?setTimeout(r,9,f):f()}
r(function(){/*code to run*/});
或本机函数,如果您只需要支持新的浏览器(与jQuery ready不同,如果在页面加载后添加它,则无法运行)
document.addEventListener('DOMContentLoaded',function(){/*fun code to run*/})
答案 2 :(得分:196)
三个选项:
script
是正文的最后一个标记,那么DOM将在脚本标记执行之前就绪。<强> 的onreadystatechange 强>
document.onreadystatechange = function () {
if (document.readyState == "complete") {
// document is ready. Do your stuff here
}
}
来源:MDN
<强> DOMContentLoaded 强>
document.addEventListener('DOMContentLoaded', function() {
console.log('document is ready. I can sleep now');
});
关注石器时代的浏览器:
转到jQuery源代码并使用ready
函数。在这种情况下,你没有解析+执行整个库,你只做了很小的一部分。
答案 3 :(得分:85)
将<script>/*JavaScript code*/</script>
右侧放在收尾 </body>
标记之前。
不可否认,这可能不适合每个人的目的,因为它需要更改HTML文件而不是仅仅在JavaScript文件中执行某些操作document.ready
,但仍然......
答案 4 :(得分:67)
穷人的解决方案:
var checkLoad = function() {
document.readyState !== "complete" ? setTimeout(checkLoad, 11) : alert("loaded!");
};
checkLoad();
添加了这个,我想更好一点,拥有范围,非递归
(function(){
var tId = setInterval(function() {
if (document.readyState == "complete") onComplete()
}, 11);
function onComplete(){
clearInterval(tId);
alert("loaded!");
};
})()
答案 5 :(得分:34)
我用这个:
document.addEventListener("DOMContentLoaded", function(event) {
//Do work
});
注意:这可能仅适用于较新的浏览器,尤其是:http://caniuse.com/#feat=domcontentloaded
答案 6 :(得分:20)
真的,如果您只关心 Internet Explorer 9+ ,此代码就足以取代jQuery.ready
:
document.addEventListener("DOMContentLoaded", callback);
如果您担心Internet Explorer 6以及一些非常奇怪和罕见的浏览器,这将有效:
domReady: function (callback) {
// Mozilla, Opera and WebKit
if (document.addEventListener) {
document.addEventListener("DOMContentLoaded", callback, false);
// If Internet Explorer, the event model is used
} else if (document.attachEvent) {
document.attachEvent("onreadystatechange", function() {
if (document.readyState === "complete" ) {
callback();
}
});
// A fallback to window.onload, that will always work
} else {
var oldOnload = window.onload;
window.onload = function () {
oldOnload && oldOnload();
callback();
}
}
},
答案 7 :(得分:18)
很久以前就提出过这个问题。对于刚刚看到这个问题的人来说,现在有一个名为"you might not need jquery"的网站,它按照所需的IE支持级别进行细分 - 所有jquery的功能都提供了一些替代的,更小的库。
的IE8文档就绪脚本function ready(fn) {
if (document.readyState != 'loading')
fn();
else if (document.addEventListener)
document.addEventListener('DOMContentLoaded', fn);
else
document.attachEvent('onreadystatechange', function() {
if (document.readyState != 'loading')
fn();
});
}
答案 8 :(得分:13)
我最近在移动网站上使用它。这是John Resig的“Pro JavaScript Techniques”简化版。这取决于addEvent。
var ready = ( function () {
function ready( f ) {
if( ready.done ) return f();
if( ready.timer ) {
ready.ready.push(f);
} else {
addEvent( window, "load", isDOMReady );
ready.ready = [ f ];
ready.timer = setInterval(isDOMReady, 13);
}
};
function isDOMReady() {
if( ready.done ) return false;
if( document && document.getElementsByTagName && document.getElementById && document.body ) {
clearInterval( ready.timer );
ready.timer = null;
for( var i = 0; i < ready.ready.length; i++ ) {
ready.ready[i]();
}
ready.ready = null;
ready.done = true;
}
}
return ready;
})();
答案 9 :(得分:11)
现在是2020年,<script>
标签具有defer
属性。
例如:
<script src="demo_defer.js" defer></script>
它指定在页面分析完成后执行脚本。
答案 10 :(得分:11)
jQuery的答案对我来说非常有用。通过一点点重构,它很好地满足了我的需求。 我希望它可以帮助其他任何人。
function onReady ( callback ){
var addListener = document.addEventListener || document.attachEvent,
removeListener = document.removeEventListener || document.detachEvent
eventName = document.addEventListener ? "DOMContentLoaded" : "onreadystatechange"
addListener.call(document, eventName, function(){
removeListener( eventName, arguments.callee, false )
callback()
}, false )
}
答案 11 :(得分:10)
跨浏览器(旧浏览器)和简单的解决方案:
var docLoaded = setInterval(function () {
if(document.readyState !== "complete") return;
clearInterval(docLoaded);
/*
Your code goes here i.e. init()
*/
}, 30);
答案 12 :(得分:9)
以下是测试DOM就绪的最小代码段,适用于所有浏览器(甚至是IE 8):
commit 64744646e9be93dd758ca5cf202c6605accf4deb
Author: Jack Nagel <jacknagel@gmail.com>
Date: Sat Jul 5 19:28:15 2014 -0500
Remove remaining references to "--fresh"
This option was removed in 8cdf4d8ebf439eb9a9ffcaa0e455ced9459e1e41
because it did not do anything.
请参阅此answer。
答案 13 :(得分:6)
只需将其添加到HTML页面的底部......
<script>
Your_Function();
</script>
因为HTML文档是由上下解析的。
答案 14 :(得分:4)
这个跨浏览器代码将在DOM准备就绪后调用函数:
var domReady=function(func){
var scriptText='('+func+')();';
var scriptElement=document.createElement('script');
scriptElement.innerText=scriptText;
document.body.appendChild(scriptElement);
};
以下是它的工作原理:
domReady
的第一行调用函数的toString
方法来获取传入函数的字符串表示形式,并将其包装在一个立即调用该函数的表达式中。domReady
的其余部分使用表达式创建一个脚本元素,并将其附加到文档的body
。body
的脚本标记。例如,如果您执行此操作:domReady(function(){alert();});
,以下内容将附加到body
元素:
<script>(function (){alert();})();</script>
请注意,这仅适用于用户定义的函数。以下操作无效:domReady(alert);
答案 15 :(得分:4)
值得查看 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");});
答案 16 :(得分:3)
这个解决方案怎么样?
// other onload attached earlier
window.onload=function() {
alert('test');
};
tmpPreviousFunction=window.onload ? window.onload : null;
// our onload function
window.onload=function() {
alert('another message');
// execute previous one
if (tmpPreviousFunction) tmpPreviousFunction();
};
答案 17 :(得分:3)
与jQuery相比,使用JavaScript等价物总是好的。一个原因是要依赖的库少一个,它们比jQuery等同得多。
jQuery等价物的一个很棒的参考是http://youmightnotneedjquery.com/。
就你的问题而言,我从上面的链接中获取了以下代码:) 唯一需要注意的是它只适用于Internet Explorer 9及以后。
function ready(fn) {
if (document.readyState != 'loading') {
fn();
}
else {
document.addEventListener('DOMContentLoaded', fn);
}
}
答案 18 :(得分:2)
我从PlainJS中选择了答案,对我来说很好。它扩展了DOMContentLoaded
,因此可以在所有浏览器中接受。
此函数等效于jQuery的$(document).ready()
方法:
document.addEventListener('DOMContentLoaded', function(){
// do something
});
但是,与jQuery相比,此代码只能在现代浏览器(IE> 8)中正常运行,并且在插入脚本(例如通过Ajax)时文档已经渲染的情况下,它不会。因此,我们需要对此进行一些扩展:
function run() {
// do something
}
// in case the document is already rendered
if (document.readyState!='loading') run();
// modern browsers
else if (document.addEventListener)
document.addEventListener('DOMContentLoaded', run);
// IE <= 8
else document.attachEvent('onreadystatechange', function(){
if (document.readyState=='complete') run();
});
这基本上涵盖了所有可能性,并且是jQuery帮助器的可行替代。
答案 19 :(得分:2)
我们发现了一个快速而又脏的跨浏览器实现,可以通过最少的实现来解决大多数简单案例:
window.onReady = function onReady(fn){
document.body ? fn() : setTimeout(function(){ onReady(fn);},50);
};
答案 20 :(得分:2)
此处提供的setTimeout / setInterval解决方案仅适用于特定情况。
问题显示在最新版本为8的旧版Internet Explorer中。
影响这些setTimeout / setInterval解决方案成功的变量是:
1) dynamic or static HTML
2) cached or non cached requests
3) size of the complete HTML document
4) chunked or non chunked transfer encoding
解决此特定问题的原始(本机Javascript)代码在此处:
https://github.com/dperini/ContentLoaded
http://javascript.nwbox.com/ContentLoaded (test)
这是jQuery团队构建其实现的代码。
答案 21 :(得分:1)
这里(在下面的代码片段中)是对所选可用浏览器“内置”方法及其执行顺序的比较。备注
document.onload
(X)(事件永远不会fired)<body onload="bodyOnLoad()">
(F)和window.onload
(E),则只会执行第一个(因为它会覆盖第二个)<body onload="...">
(F)中给出的onload
函数包装document.onreadystatechange
(D)不覆盖document .addEventListener('readystatechange'...)
(C)可能是由于onXYZevent-like
方法独立于addEventListener
队列(允许添加多个侦听器)。在执行这两个处理程序之间可能什么也没发生。div
的脚本也将其时间戳也写入正文中(在脚本执行后单击“全页”链接以查看时间戳)。readystatechange
(C,D)被浏览器多次执行,但针对不同的文档状态:DOMContentLoaded
之前触发body/window onload
之前触发
<html>
<head>
<script>
// solution A
console.log(`[timestamp: ${Date.now()}] A: Head script`) ;
// solution B
document.addEventListener("DOMContentLoaded", () => {
print(`[timestamp: ${Date.now()}] B: DOMContentLoaded`);
});
// solution C
document.addEventListener('readystatechange', () => {
print(`[timestamp: ${Date.now()}] C: ReadyState: ${document.readyState}`);
});
// solution D
document.onreadystatechange = s=> {print(`[timestamp: ${Date.now()}] D: document.onreadystatechange ReadyState: ${document.readyState}`)};
// solution E (never executed)
window.onload = () => {
print(`E: <body onload="..."> override this handler`);
};
// solution F
function bodyOnLoad() {
print(`[timestamp: ${Date.now()}] F: <body onload='...'>`);
infoAboutOnLoad(); // additional info
}
// solution X
document.onload = () => {print(`document.onload is never fired`)};
// HELPERS
function print(txt) {
console.log(txt);
if(mydiv) mydiv.innerHTML += txt.replace('<','<').replace('>','>') + '<br>';
}
function infoAboutOnLoad() {
console.log("window.onload (after override):", (''+document.body.onload).replace(/\s+/g,' '));
console.log(`body.onload==window.onload --> ${document.body.onload==window.onload}`);
}
console.log("window.onload (before override):", (''+document.body.onload).replace(/\s+/g,' '));
</script>
</head>
<body onload="bodyOnLoad()">
<div id="mydiv"></div>
<!-- this script must te at the bottom of <body> -->
<script>
// solution G
print(`[timestamp: ${Date.now()}] G: <body> bottom script`);
</script>
</body>
</html>
答案 22 :(得分:1)
这应该有效:
document.addEventListener('DOMContentLoaded', function() {
/* alert('Page loaded!');
some code
more code */
});
答案 23 :(得分:1)
如果您不必支持非常旧的浏览器,即使您的外部脚本加载了 async 属性,也可以通过以下方式执行此操作:
HTMLDocument.prototype.ready = new Promise(function(resolve) {
if(document.readyState != "loading")
resolve();
else
document.addEventListener("DOMContentLoaded", function() {
resolve();
});
});
document.ready.then(function() {
console.log("document.ready");
});
答案 24 :(得分:1)
这是我使用的,它的速度快,涵盖了我认为的所有基础;适用于除IE&lt; 9。
之外的所有内容(() => { function fn() {
// "On document ready" commands:
console.log(document.readyState);
};
if (document.readyState != 'loading') {fn()}
else {document.addEventListener('DOMContentLoaded', fn)}
})();
这似乎抓住了所有情况:
DOMContentLoaded事件在IE9和其他所有内容中都可用,因此我个人认为使用它是可以的。如果您没有将代码从ES2015转换为ES5,请将箭头函数声明重写为常规匿名函数。
如果你想等到所有资产都被加载,所有显示的图像等都会使用window.onload。
答案 25 :(得分:0)
对于IE9 +:
function ready(fn) {
if (document.readyState != 'loading'){
fn();
} else {
document.addEventListener('DOMContentLoaded', fn);
}
}
答案 26 :(得分:0)
这种方法是我能想到的最短路。
基于DOMContentLoaded事件的解决方案仅在脚本在文档之前加载时才有效,而此处建议的延迟检查确保代码始终执行,即使在稍后动态加载的脚本中也是如此,与JQuery的完全相同准备好文件。
此代码与所有浏览器兼容(包括一些旧版本,适用于IE6和Safari for Windows)。
(function ready() {
if (!document.body) {setTimeout(ready, 50); return;}
// Document is ready here
})();
答案 27 :(得分:0)
function onDocReady(fn){
$d.readyState!=="loading" ? fn():document.addEventListener('DOMContentLoaded',fn);
}
function onWinLoad(fn){
$d.readyState==="complete") ? fn(): window.addEventListener('load',fn);
}
当HTML dom准备好完全访问/解析/操作时,onDocReady 会提供回调。
onWinLoad 在所有内容都已加载(图片等)时提供回调
答案 28 :(得分:0)
试试这个:
function ready(callback){
if(typeof callback === "function"){
document.addEventListener("DOMContentLoaded", callback);
window.addEventListener("load", callback);
}else{
throw new Error("Sorry, I can not run this!");
}
}
ready(function(){
console.log("It worked!");
});
答案 29 :(得分:0)
(function(f){
if(document.readyState != "loading") f();
else document.addEventListener("DOMContentLoaded", f);
})(function(){
console.log("The Document is ready");
});
答案 30 :(得分:0)
大多数香草JS Ready函数不会考虑在文档已经加载后<{> 设置DOMContentLoaded
处理程序的情况-这意味着该函数将永远不会运行。如果您在DOMContentLoaded
外部脚本(async
)中寻找<script async src="file.js"></script>
,则会发生这种情况。
仅当文档的DOMContentLoaded
尚未readyState
或interactive
时,下面的代码才检查complete
。
var DOMReady = function(callback) {
document.readyState === "interactive" || document.readyState === "complete" ? callback() : document.addEventListener("DOMContentLoaded", callback());
};
DOMReady(function() {
//DOM ready!
});
如果您也要支持IE:
var DOMReady = function(callback) {
if (document.readyState === "interactive" || document.readyState === "complete") {
callback();
} else if (document.addEventListener) {
document.addEventListener('DOMContentLoaded', callback());
} else if (document.attachEvent) {
document.attachEvent('onreadystatechange', function() {
if (document.readyState != 'loading') {
callback();
}
});
}
};
DOMReady(function() {
// DOM ready!
});
答案 31 :(得分:0)
如果您在BODY底部附近加载jQuery,但是在编写jQuery(&lt; func&gt;)或jQuery(document).ready(&lt; func&gt;)的代码时遇到问题,请查看{{3}在Github上。
它不是重新创建自己的文档就绪函数,而是简单地保留函数,直到jQuery可用,然后按预期继续jQuery。将jQuery移动到body的底部是为了加快页面加载,你仍然可以通过在模板的头部内联jqShim.min.js来实现它。
我最后编写了这段代码,以便将jqShim中的所有脚本移动到页脚,而这个填充码现在直接位于页眉中。
答案 32 :(得分:0)
在所有已知的浏览器中运行(通过BrowserStack测试)。 IE6 +,Safari 1 +,Chrome 1 +,Opera等。使用DOMContentLoaded
,后退到document.documentElement.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>
答案 33 :(得分:0)
现在,您应该使用模块。将代码放入模块的默认功能中,然后将该功能导入脚本元素中。
binding
:
setContentView()
client.js
:
export default function ()
{
alert ("test");
}
答案 34 :(得分:0)
jQuery
中的就绪功能做了很多事情。坦率地说,除非你的网站产量非常小,否则我没有看到更换它的重点。 jQuery
是一个非常小的库,它可以处理以后需要的各种跨浏览器。
无论如何,在此处发布它没什么意义,只需打开jQuery
并查看bindReady
方法。
首先根据事件模型调用document.addEventListener("DOMContentLoaded")
或document.attachEvent('onreadystatechange')
,然后从那里继续。
答案 35 :(得分:-1)
编辑@duskwuff编辑以支持Internet Explorer 8。区别在于对正则表达式的函数测试和带有匿名函数的setTimeout的新调用。
另外,我将超时设置为99。
function ready(f){/in/.test(document.readyState)?setTimeout(function(){ready(f);},99):f();}
答案 36 :(得分:-1)
这是一个很好的https://stackoverflow.com/a/11810957/185565穷人的解决方案。一条评论认为,在紧急情况下应该采取救助措施。这是我的修改。
function doTheMagic(counter) {
alert("It worked on " + counter);
}
// wait for document ready then call handler function
var checkLoad = function(counter) {
counter++;
if (document.readyState != "complete" && counter<1000) {
var fn = function() { checkLoad(counter); };
setTimeout(fn,10);
} else doTheMagic(counter);
};
checkLoad(0);
答案 37 :(得分:-4)
简而言之,我们可以使用JavaScript方法代替jQuery中使用的$(document).ready():
<script>
document.addEventListener("DOMContentLoaded", function_name, false);
function function_name(){
statements;
}
</script>
因此,当页面准备就绪,即只有DOMContentLoaded时,将调用函数function_name()。
答案 38 :(得分:-7)
如果你想支持 Internet Explorer 7+(没有怪癖,兼容性和其他痛苦),最后Chrome,最后Safari,最后一个Firefox,没有iframe - 这就足够了:
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