我有一个使用$(document).ready的脚本,但它不使用jQuery中的任何其他内容。我想通过删除jQuery依赖项来减轻它。
如何在不使用jQuery的情况下实现我自己的$(document).ready功能?我知道,使用window.onload将不同,因为window.onlead在加载所有图像、帧等后启动。
我有一个使用$(document).ready的脚本,但它不使用jQuery中的任何其他内容。我想通过删除jQuery依赖项来减轻它。
如何在不使用jQuery的情况下实现我自己的$(document).ready功能?我知道,使用window.onload将不同,因为window.onlead在加载所有图像、帧等后启动。
当前回答
比较
这里(在下面的片段中)是所选择的可用浏览器“内置”方法及其执行顺序的比较。评论
任何现代浏览器都不支持document.onload(X)(从不触发事件)如果您使用<body onload=“bodyOnLoad()”>(F),同时使用window.onload(E),则只执行第一个(因为它会覆盖第二个)<body onload=“…”>(F)中给定的事件处理程序由附加的onload函数包装document.onreadystatechange(D)不覆盖document.addEventListener('readystatechange'…)(C)可能是因为类似XYZevent的方法独立于addEventListener队列(允许添加多个侦听器)。在执行这两个处理程序之间可能不会发生任何事情。所有脚本都在控制台中写入时间戳,但也可以访问div的脚本也在主体中写入时间标记(在脚本执行后单击“FullPage”链接查看)。解决方案readystatechange(C,D)由浏览器执行多次,但针对不同的文档状态:loading-文档正在加载(没有在代码段中激发)交互式-文档在DOMContentLoaded之前被解析和激发完成-加载文档和资源,在加载body/window之前激发
<html><head><脚本>//溶液Aconsole.log(`[timestamp:${Date.now()}]A:Head脚本`);//溶液Bdocument.addEventListener(“DOMContentLoaded”,()=>{print(`[时间戳:${Date.now()}]B:DOMContentLoaded`);});//溶液Cdocument.addEventListener('readystatechange',()=>{print(`[时间戳:${Date.now()}]C:就绪状态:${document.ReadyState}`);});//溶液Ddocument.onreadystatechange=s=>{print(`[时间戳:${Date.now()}]D:document.onrreadystatechange就绪状态:${document.ReadyState}`)};//解决方案E(从未执行)window.onload=()=>{print(`E:<body onload=“…”>覆盖此处理程序`);};//溶液F函数体OnLoad(){print(`[timestamp:${Date.now()}]F:<body onload='…'>`);infoAboutOnLoad();//其他信息}//溶液Xdocument.onload=()=>{print(“document.onlead从未启动”)};//助手函数打印(txt){console.log(txt);如果(mydiv)mydiv.innerHTML+=txt.replace('<','<;').replace('>','>;')+'<br>';}函数infoAboutOnLoad(){console.log(“window.onload(重写后):”,(“”+document.body.onload).replace(/\s+/g,“”));console.log(`body.onload==window.onload-->${document.body.onload==window.onload}`);}console.log(“window.onload(覆盖前):”,(“”+document.body.onload).replace(/\s+/g,“”));</script></head><body onload=“bodyOnLoad()”><div id=“mydiv”></div><!-- 此脚本必须位于<body>-->的底部<脚本>//溶液Gprint(`[timestamp:${Date.now()}]G:<body>底部脚本`);</script></body></html>
其他回答
我们发现了一个快速而肮脏的跨浏览器实现,它可以用最少的实现实现大多数简单情况:
window.onReady = function onReady(fn){
document.body ? fn() : setTimeout(function(){ onReady(fn);},50);
};
我最近在一个移动网站上使用这个。这是John Resig的简化版“Pro JavaScript技术”。它取决于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;
})();
与jQuery相比,使用JavaScript等价物总是很好的。一个原因是依赖的库少了一个,而且它们比jQuery等同物快得多。
jQuery等价物的一个极好的参考是http://youmightnotneedjquery.com/.
就您的问题而言,我从上面的链接中获取了以下代码:)唯一需要注意的是,它仅适用于Internet Explorer 9及更高版本。
function ready(fn) {
if (document.readyState != 'loading') {
fn();
}
else {
document.addEventListener('DOMContentLoaded', fn);
}
}
jQuery中的ready函数做了很多事情。坦率地说,除非你的网站有惊人的小输出,否则我看不出替换它的意义。jQuery是一个非常小的库,它处理您稍后需要的各种跨浏览器的事情。
无论如何,在这里发布它没有什么意义,只需打开jQuery并查看bindReady方法。
它首先根据事件模型调用document.addEventListener(“DOMContentLoaded”)或document.attachEvent(“unreadystatechange”),然后继续。
如果你想支持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