与jQuery的$ .ready()完全相同的JavaScript-当页面/ DOM准备就绪时如何调用函数[重复]

问题描述 投票:1198回答:10

此问题已经在这里有了答案:

[好吧,这可能只是一个愚蠢的问题,尽管我敢肯定会有很多其他人不时问同样的问题。我,我只是想以任何一种方式100%确定它。使用jQuery,我们都知道很棒]

$('document').ready(function(){});

但是,我想运行一个用标准JavaScript编写的函数,而没有库支持它,我想在页面准备好处理后立即启动一个函数。解决这个问题的正确方法是什么?

我知道我可以做到:

window.onload="myFunction()";

...或者我可以使用body标签:

<body onload="myFunction()">

...或者我什至可以在页面底部尝试所有内容,但结尾bodyhtml标签如下:

<script type="text/javascript">
   myFunction();
</script>

什么是跨浏览器(旧/新)兼容的方法,以类似于jQuery的$.ready()的方式发布一个或多个函数?

javascript jquery html
10个回答
1715
投票
<!doctype html> <html> <head> </head> <body> Your HTML here <script> // self executing function here (function() { // your page initialization code here // the DOM will be available here })(); </script> </body> </html>

[对于现代浏览器(来自IE9和更高版本以及任何版本的Chrome,Firefox或Safari),如果您希望能够实现类似$(document).ready()的jQuery,则可以从任何地方调用(而不必担心调用位置)脚本的位置),您可以只使用以下内容:
function docReady(fn) { // see if DOM is already available if (document.readyState === "complete" || document.readyState === "interactive") { // call on next available tick setTimeout(fn, 1); } else { document.addEventListener("DOMContentLoaded", fn); } }

用法:

docReady(function() {
    // DOM is loaded and ready for manipulation here
});

如果您需要完全的跨浏览器兼容性(包括旧版本的IE),并且不想等待window.onload,那么您可能应该看看jQuery之类的框架如何实现其$(document).ready()方法。根据浏览器的功能,它相当复杂。
为了让您稍微了解一下jQuery的功能(在放置script标记的任何地方都可以使用。)>

[如果支持,它将尝试标准:

document.addEventListener('DOMContentLoaded', fn, false);

回退到:

window.addEventListener('load', fn, false )

或对于较旧版本的IE,它使用:

document.attachEvent("onreadystatechange", fn);

回退到:

window.attachEvent("onload", fn);

而且,IE代码路径中有一些变通办法,我不太了解,但似乎与框架有关。

这里是用普通JavaScript编写的jQuery .ready()的完全替代:


(function(funcName, baseObj) { // The public function name defaults to window.docReady // but you can pass in your own object and own function name and those will be used // if you want to put them in a different namespace funcName = funcName || "docReady"; baseObj = baseObj || window; var readyList = []; var readyFired = false; var readyEventHandlersInstalled = false; // call this when the document is ready // this function protects itself against being called more than once function ready() { if (!readyFired) { // this must be set to true before we start calling callbacks readyFired = true; for (var i = 0; i < readyList.length; i++) { // if a callback here happens to add new ready handlers, // the docReady() function will see that it already fired // and will schedule the callback to run right after // this event loop finishes so all handlers will still execute // in order and no new ones will be added to the readyList // while we are processing the list readyList[i].fn.call(window, readyList[i].ctx); } // allow any closures held by these functions to free readyList = []; } } function readyStateChange() { if ( document.readyState === "complete" ) { ready(); } } // This is the one public interface // docReady(fn, context); // the context argument is optional - if present, it will be passed // as an argument to the callback baseObj[funcName] = function(callback, context) { if (typeof callback !== "function") { throw new TypeError("callback for docReady(fn) must be a function"); } // if ready has already fired, then just schedule the callback // to fire asynchronously, but right away if (readyFired) { setTimeout(function() {callback(context);}, 1); return; } else { // add the function and context to the list readyList.push({fn: callback, ctx: context}); } // if document already ready to go, schedule the ready function to run if (document.readyState === "complete") { setTimeout(ready, 1); } else if (!readyEventHandlersInstalled) { // otherwise if we don't have event handlers installed, install them if (document.addEventListener) { // first choice is DOMContentLoaded event document.addEventListener("DOMContentLoaded", ready, false); // backup is window load event window.addEventListener("load", ready, false); } else { // must be IE document.attachEvent("onreadystatechange", readyStateChange); window.attachEvent("onload", ready); } readyEventHandlersInstalled = true; } } })("docReady", window);

该代码的最新版本已在GitHub的https://github.com/jfriend00/docReady上公开共享

用法:

// pass a function reference docReady(fn); // use an anonymous function docReady(function() { // code here }); // pass a function reference and a context // the context will be passed to the function as the first argument docReady(fn, context); // use an anonymous function with a context docReady(function(context) { // code here that can use the context argument that was passed to docReady }, ctx);

已在以下位置进行测试:

IE6 and up Firefox 3.6 and up Chrome 14 and up Safari 5.1 and up Opera 11.6 and up Multiple iOS devices Multiple Android devices

工作实施和测试平台:http://jsfiddle.net/jfriend00/YfD3C/

以下是其工作原理的摘要:


创建IIFE(立即调用的函数表达式),以便我们可以使用非公共状态变量。

    声明公共功能docReady(fn, context)
  1. 当调用docReady(fn, context)时,检查就绪处理程序是否已经触发。如果是这样,只需安排新添加的回调在此JS线程以setTimeout(fn, 1)完成后立即触发。
  2. 如果就绪处理程序尚未触发,则将此新回调添加到稍后要调用的回调列表中。
  3. 检查文档是否已经准备好。如果是这样,请执行所有就绪的处理程序。
  4. 如果尚未安装事件监听器,不知道文档准备就绪的时间,请立即安装它们。
  5. 如果存在document.addEventListener,则对.addEventListener()"DOMContentLoaded"事件都使用"load"安装事件处理程序。为了安全起见,“负载”是备用事件,因此不需要。
  6. 如果document.addEventListener不存在,则使用.attachEvent()"onreadystatechange"事件使用"onload"安装事件处理程序。
  7. onreadystatechange事件中,检查以查看是否document.readyState === "complete",如果是,请调用一个函数以激发所有就绪的处理程序。
  8. [在所有其他事件处理程序中,调用一个函数以激发所有就绪的处理程序。
  9. 在调用所有就绪处理程序的函数中,检查一个状态变量以查看是否已经解雇。如果有,什么也不做。如果尚未调用,请遍历准备好的函数数组,并按添加顺序调用每个函数。设置一个标志以指示所有这些都已被调用,因此它们永远不会被执行多次。
  10. 清除函数数组,以便释放它们可能正在使用的所有闭包。
  11. 保证用docReady()注册的处理程序将按照其注册顺序被触发。
  12. 如果在文档准备就绪后调用docReady(fn),则将安排使用setTimeout(fn, 1)在当前执行线程完成后立即执行回调。这使调用代码始终可以认为它们是异步回调,即使稍后在当前JS线程完成并保留调用顺序时也将稍后调用。

我想在这里与
适用于所有浏览器的纯JavaScript技巧]一起提一些可​​能的方法:]

// with jQuery $(document).ready(function(){ /* ... */ }); // shorter jQuery version $(function(){ /* ... */ }); // without jQuery (doesn't work in older IEs) document.addEventListener('DOMContentLoaded', function(){ // your code goes here }, false); // and here's the trick (works everywhere) function r(f){/in/.test(document.readyState)?setTimeout('r('+f+')',9):f()} // use like r(function(){ alert('DOM Ready!'); });

这里的窍门,正如[C​​0]所解释的,是我们正在检查
document.readyState
属性。如果它包含字符串original author(与inuninitialized相同,则为5中的前两个loading),我们设置超时并再次检查。否则,我们将执行传递的函数。

这是该技巧的DOM ready states,[在所有浏览器中均可使用。

感谢jsFiddle将其包含在他们的书中。

如果您在没有jQuery的情况下执行

VANILLA纯
JavaScript,则必须使用(Internet Explorer 9或更高版本:]]

Tutorialzine

以上等同于jQuery document.addEventListener("DOMContentLoaded", function(event) { // Your code to run since DOM is loaded and ready });
.ready
还可以这样写,其中jQuery将在$(document).ready(function() {
    console.log("Ready!");
});
就绪后运行。

occurs

不要与下面混淆

(这并不意味着要准备DOM):
请勿使用像这样自执行的$(function() {
    console.log("ready!");
});

IIFE

此IIFE不会等待您的DOM加载。 (我什至在谈论最新版本的Chrome浏览器!)

在IE9,最新的Firefox和Chrome中测试,并在IE8中也受支持。

Example: (function() { // Your page initialization code here - WRONG // The DOM will be available here - WRONG })();
示例:document.onreadystatechange = function () { var state = document.readyState; if (state == 'interactive') { init(); } else if (state == 'complete') { initOnCompleteLoad(); } }​;

更新-可重用版本

我刚刚开发了以下内容。这与没有向后兼容性的jQuery或Dom相当简单。它可能需要进一步完善。已在最新版本的Chrome,Firefox和IE(10/11)中进行了测试,并可以在旧版浏览器中运行,如注释所述。如果发现任何问题,我会进行更新。

http://jsfiddle.net/electricvisions/Jacck/

用法:

window.readyHandlers = []; window.ready = function ready(handler) { window.readyHandlers.push(handler); handleState(); }; window.handleState = function handleState () { if (['interactive', 'complete'].indexOf(document.readyState) > -1) { while(window.readyHandlers.length > 0) { (window.readyHandlers.shift())(); } } }; document.onreadystatechange = window.handleState;

它是为处理JS的异步加载而编写的,但是除非您精简,否则您可能希望先对其进行同步加载。我发现它在开发中很有用。

现代浏览器还支持异步加载脚本,从而进一步增强了体验。支持异步意味着可以同时下载多个脚本,同时仍渲染页面。只需注意何时依赖于异步加载的其他脚本,或者使用缩小器或类似browserify的东西来处理依赖项。

HubSpot的好伙伴有一个资源,您可以在其中找到用于实现许多jQuery优点的纯Javascript方法论-包括ready(function () { // your code here });

ready
http://youmightnotneedjquery.com/#ready

示例内联用法:

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(); }); } }

您的方法(将脚本放在结束body标记之前)
ready(function() { alert('hello'); });
是支持新旧浏览器的可靠方法。

我不确定您要问的是什么,但这也许可以帮助您:

<script> myFunction() </script> </body> </html>
或:

window.onload = function(){ // Code. . . }

就绪
window.onload = main; function main(){ // Code. . . }
使用方式

function ready(fn){var d=document;(d.readyState=='loading')?d.addEventListener('DOMContentLoaded',fn):fn();}

用于自调用代码

ready(function(){
    //some code
});

支持:IE9 +


这里是(function(fn){var d=document;(d.readyState=='loading')?d.addEventListener('DOMContentLoaded',fn):fn();})(function(){ //Some Code here //DOM is avaliable //var h1s = document.querySelector("h1"); }); 的清理后的非评估版,“在所有浏览器中均可使用”,在所有浏览器中均可使用!

Ram-swaroop's
但是,它确实要等待额外的10毫秒才能运行,因此,这是不应该使用的更复杂的方法:

function onReady(yourMethod) { var readyStateCheckInterval = setInterval(function() { if (document && document.readyState === 'complete') { // Or 'interactive' clearInterval(readyStateCheckInterval); yourMethod(); } }, 10); } // use like onReady(function() { alert('hello'); } );

另请参阅

function onReady(yourMethod) { if (document.readyState === 'complete') { // Or also compare to 'interactive' setTimeout(yourMethod, 1); // Schedule to run immediately } else { readyStateCheckInterval = setInterval(function() { if (document.readyState === 'complete') { // Or also compare to 'interactive' clearInterval(readyStateCheckInterval); yourMethod(); } }, 10); } } // Use like onReady(function() { alert('hello'); } ); // Or onReady(functionName);

How to check if DOM is ready without a framework?应该可以解决问题,但它不具有完全的浏览器兼容性。

似乎您应该只使用jQuery min

1
投票

146
投票
适用于所有浏览器的纯JavaScript技巧]一起提一些可​​能的方法:]

// with jQuery $(document).ready(function(){ /* ... */ }); // shorter jQuery version $(function(){ /* ... */ }); // without jQuery (doesn't work in older IEs) document.addEventListener('DOMContentLoaded', function(){ // your code goes here }, false); // and here's the trick (works everywhere) function r(f){/in/.test(document.readyState)?setTimeout('r('+f+')',9):f()} // use like r(function(){ alert('DOM Ready!'); });


127
投票
JavaScript,则必须使用(Internet Explorer 9或更高版本:]]

Tutorialzine


77
投票
示例:document.onreadystatechange = function () { var state = document.readyState; if (state == 'interactive') { init(); } else if (state == 'complete') { initOnCompleteLoad(); } }​;

更新-可重用版本

19
投票

7
投票
是支持新旧浏览器的可靠方法。

6
投票
或:

window.onload = function(){ // Code. . . }


4
投票
使用方式

function ready(fn){var d=document;(d.readyState=='loading')?d.addEventListener('DOMContentLoaded',fn):fn();}


3
投票
但是,它确实要等待额外的10毫秒才能运行,因此,这是不应该使用的更复杂的方法:

function onReady(yourMethod) { var readyStateCheckInterval = setInterval(function() { if (document && document.readyState === 'complete') { // Or 'interactive' clearInterval(readyStateCheckInterval); yourMethod(); } }, 10); } // use like onReady(function() { alert('hello'); } );

© www.soinside.com 2019 - 2024. All rights reserved.