非jquery的'$(document).ready()'

非jquery的$(document).ready()的对等物是什么?

330366 次浏览

在普通的JavaScript中,没有库?这是一个错误。$只是一个标识符,除非您定义它,否则它是未定义的。

jQuery将$定义为它自己的“所有对象”(也称为jQuery,这样您就可以在不与其他库冲突的情况下使用它)。如果你没有使用jQuery(或其他定义它的库),那么$将不会被定义。

或者你是在问在纯JavaScript中有什么等价的东西吗?在这种情况下,您可能需要window.onload,它并不完全相同,但它是在普通JavaScript中接近相同效果的最快、最简单的方法。

这没有回答问题,也没有显示任何非jquery代码。请看下面@ sospedra的回答。

关于$(document).ready()的好处是它在window.onload之前被触发。load函数等待加载所有内容,包括外部资产和图像。但是,$(document).ready在DOM树完成并且可以操作时触发。如果你想在没有jQuery的情况下实现DOM,你可以查看这个库。有人从jQuery中提取了ready部分。它又小又漂亮,你可能会发现它很有用:

domready at谷歌Code

这从ECMA完美地工作。这段代码是您所需要的全部内容,但如果您想挖掘更多内容并探索其他选项,请检查详细解释

document.addEventListener("DOMContentLoaded", function() {
// code...
});

window.onload不等于JQuery的$(document).ready,因为$(document).ready只等待DOM树,而window.onload检查所有元素,包括外部资产和图像。

编辑:由于Jan Derk的观察,添加了IE8和更老的等效版本。你可以在MDN上阅读此代码的源代码:

// alternative to DOMContentLoaded
document.onreadystatechange = function () {
if (document.readyState == "interactive") {
// Initialize your application or run some code.
}
}

除了"interactive",还有其他选项。详见MDN文档

我拼凑的一个小东西

domready.js

(function(exports, d) {
function domReady(fn, context) {


function onReady(event) {
d.removeEventListener("DOMContentLoaded", onReady);
fn.call(context || exports, event);
}


function onReadyIe(event) {
if (d.readyState === "complete") {
d.detachEvent("onreadystatechange", onReadyIe);
fn.call(context || exports, event);
}
}


d.addEventListener && d.addEventListener("DOMContentLoaded", onReady) ||
d.attachEvent      && d.attachEvent("onreadystatechange", onReadyIe);
}


exports.domReady = domReady;
})(window, document);

如何使用

<script src="domready.js"></script>
<script>
domReady(function(event) {
alert("dom is ready!");
});
</script>

您还可以通过传递第二个参数来更改回调运行的上下文

function init(event) {
alert("check the console");
this.log(event);
}


domReady(init, console);

主体onLoad也可以是一个替代方案:

<html>
<head><title>Body onLoad Exmaple</title>


<script type="text/javascript">
function window_onload() {
//do something
}
</script>


</head>
<body onLoad="window_onload()">


</body>
</html>

有一个基于标准的替换

DOMContentLoaded,超过90%+的浏览器支持,但不是 IE8(因此下面的代码使用JQuery浏览器支持)

document.addEventListener("DOMContentLoaded", function(event) {
//do work
});

jQuery的原生函数比窗口复杂得多。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 );
}

在最近的浏览器中最简单的方法是使用适当的< >强GlobalEventHandlers < / >强onDOMContentLoadedonloadonloadeddata(…)

onDOMContentLoaded = (function(){ console.log("DOM ready!") })()


onload = (function(){ console.log("Page fully loaded!") })()


onloadeddata = (function(){ console.log("Data loaded!") })()

当初始HTML文档完全加载和解析时,无需等待样式表、图像和子帧完成加载,就会触发DOMContentLoaded事件。应该只使用完全不同的事件加载来检测完全加载的页面。在更适合使用DOMContentLoaded的地方使用load是一个非常普遍的错误,所以要谨慎。

https://developer.mozilla.org/en-US/docs/Web/Events/DOMContentLoaded

使用的函数是一个IIFE,在这种情况下非常有用,因为它在准备好时触发自己:

https://en.wikipedia.org/wiki/Immediately-invoked_function_expression

显然,将它放在任何脚本的末尾更合适。

在ES6中,我们也可以把它写成一个箭头函数:

onload = (() => { console.log("ES6 page fully loaded!") })()

The best is to use the DOM elements, we can wait for any variable to be ready, that trigger an arrowed IIFE.

The behavior will be the same, but with less memory impact.

footer = (() => { console.log("Footer loaded!") })()
<div id="footer">

根据http://youmightnotneedjquery.com/#ready的说法,一个很好的替换仍然适用于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();
});
}
}


// test
window.ready(function() {
alert('it works');
});

改进:我个人也会检查fn的类型是否是一个函数。 并且正如@elliottregan所建议的那样,在使用后删除事件监听器

function ready(fn) {
if (typeof fn !== 'function') {
throw new Error('Argument passed to ready should be a function');
}


if (document.readyState != 'loading') {
fn();
} else if (document.addEventListener) {
document.addEventListener('DOMContentLoaded', fn, {
once: true // A boolean value indicating that the listener should be invoked at most once after being added. If true, the listener would be automatically removed when invoked.
});
} else {
document.attachEvent('onreadystatechange', function() {
if (document.readyState != 'loading')
fn();
});
}
}


// tests
try {
window.ready(5);
} catch (ex) {
console.log(ex.message);
}




window.ready(function() {
alert('it works');
});

我之所以回答这个问题晚,是因为我一直在寻找这个答案,但在这里找不到。我认为这是最好的解决办法。

现在是2018年,这里有一个快速而简单的方法。

这将添加一个事件监听器,但如果它已经被触发,我们将检查dom是否处于就绪状态或它是否完整。这可以在子资源完成加载(图像、样式表、框架等)之前或之后触发。

function domReady(fn) {
// If we're early to the party
document.addEventListener("DOMContentLoaded", fn);
// If late; I mean on time.
if (document.readyState === "interactive" || document.readyState === "complete" ) {
fn();
}
}


domReady(() => console.log("DOM is ready, come and get it!"));

额外的数据

  • https://developer.mozilla.org/en-US/docs/Web/Events/DOMContentLoaded

    更新

    下面是一些使用标准ES6导入的快速实用工具。导出我写的也包括TypeScript。也许我可以让这些快速库可以安装到项目作为一个依赖。

    JavaScript

    export const domReady = (callBack) => {
    if (document.readyState === "loading") {
    document.addEventListener('DOMContentLoaded', callBack);
    }
    else {
    callBack();
    }
    }
    
    
    export const windowReady = (callBack) => {
    if (document.readyState === 'complete') {
    callBack();
    }
    else {
    window.addEventListener('load', callBack);
    }
    }
    

    打印稿

    export const domReady = (callBack: () => void) => {
    if (document.readyState === "loading") {
    document.addEventListener('DOMContentLoaded', callBack);
    }
    else {
    callBack();
    }
    }
    
    
    export const windowReady = (callBack: () => void) => {
    if (document.readyState === 'complete') {
    callBack();
    }
    else {
    window.addEventListener('load', callBack);
    }
    }
    

    承诺

    export const domReady = new Promise(resolve => {
    if (document.readyState === "loading") {
    document.addEventListener('DOMContentLoaded', resolve);
    }
    else {
    resolve();
    }
    });
    
    
    export const windowReady = new Promise(resolve => {
    if (document.readyState === 'complete') {
    resolve();
    }
    else {
    window.addEventListener('load', resolve);
    }
    });