Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
327 views
in Technique[技术] by (71.8m points)

javascript - 纯JavaScript等效于jQuery的$ .ready()-页面/ DOM准备就绪时如何调用函数[重复](Pure JavaScript equivalent of jQuery's $.ready() - how to call a function when the page/DOM is ready for it [duplicate])

This question already has an answer here:

(这个问题已经在这里有了答案:)

Okay, this might just be a silly question, though I'm sure there are plenty of other people asking the same question from time to time.

(好的,这可能只是一个愚蠢的问题,尽管我敢肯定会有很多其他人不时问同样的问题。)

Me, I just want to make 100% sure about it either way.

(我,我只是想以任何一种方式100%确定它。)

With jQuery we all know the wonderful

(有了jQuery,我们都知道精彩之处)

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

However, let's say I want to run a function that is written in standard JavaScript with no library backing it, and that I want to launch a function as soon as the page is ready to handle it.

(但是,假设我要运行一个用标准JavaScript编写且没有库支持的函数,并且我想在页面准备好处理后立即启动一个函数。)

What's the proper way to approach this?

(解决这个问题的正确方法是什么?)

I know I can do:

(我知道我可以做:)

window.onload="myFunction()";

...or I can use the body tag:

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

<body onload="myFunction()">

...or I can even try at the bottom of the page after everything, but the end body or html tag like:

(......或者我甚至可以尝试一切后,页面的底部,但最终的bodyhtml标签,如:)

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

What is a cross-browser(old/new)-compliant method of issuing one or more functions in a manner like jQuery's $.ready() ?

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

  ask by chris translate from so

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The simplest thing to do in the absence of a framework that does all the cross-browser compatibility for you is to just put a call to your code at the end of the body.

(在没有为您提供所有跨浏览器兼容性的框架的情况下,最简单的操作就是将调用代码放在正文末尾。)

This is faster to execute than an onload handler because this waits only for the DOM to be ready, not for all images to load.

(与onload处理程序相比,这执行起来更快,因为它仅等待DOM准备就绪,而不等待所有图像加载。)

And, this works in every browser.

(而且,这适用于所有浏览器。)

<!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>

For modern browsers (anything from IE9 and newer and any version of Chrome, Firefox or Safari), if you want to be able to implement a jQuery like $(document).ready() method that you can call from anywhere (without worrying about where the calling script is positioned), you can just use something like this:

(对于现代浏览器(来自IE9和更高版本以及任何版本的Chrome,Firefox或Safari),如果您希望能够实现jQuery,例如$(document).ready()方法,您可以从任何地方调用它(而不必担心)调用脚本所在的位置),您可以使用类似以下内容的代码:)

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

Usage:

(用法:)

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

If you need full cross browser compatibility (including old versions of IE) and you don't want to wait for window.onload , then you probably should go look at how a framework like jQuery implements its $(document).ready() method.

(如果您需要完全的跨浏览器兼容性(包括IE的旧版本)并且不想等待window.onload ,那么您可能应该看看jQuery之类的框架如何实现其$(document).ready()方法。 。)

It's fairly involved depending upon the capabilities of the browser.

(根据浏览器的功能,它相当复杂。)

To give you a little idea what jQuery does (which will work wherever the script tag is placed).

(让您稍微了解一下jQuery的功能(无论将script标记放置在何处都可以使用)。)

If supported, it tries the standard:

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

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

with a fallback to:

(后退到:)

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

or for older versions of IE, it uses:

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

document.attachEvent("onreadystatechange", fn);

with a fallback to:

(后退到:)

window.attachEvent("onload", fn);

And, there are some work-arounds in the IE code path that I don't quite follow, but it looks like it has something to do with frames.

(而且,我不太了解IE代码路径中的一些变通办法,但看起来它与框架有关。)


Here is a full substitute for jQuery's .ready() written in plain javascript:

(这是用普通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);

The latest version of the code is shared publicly on GitHub at https://github.com/jfriend00/docReady

(该代码的最新版本在GitHub上公开共享, 网址https://github.com/jfriend00/docReady)

Usage:

(用法:)

// 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);

This has been tested in:

(已在以下位置进行了测试:)

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

Working implementation and test bed: http://jsfiddle.net/jfriend00/YfD3C/

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


Here's a summary of how it works:

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

  1. Create an IIFE (immediately invoked function expression) so we can have non-public state variables.

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

  2. Declare a public function docReady(fn, context)

    (声明一个公共函数docReady(fn, context))

  3. When docReady(fn, context) is called, check if the ready handler has already fired.

    (docReady(fn, context) ,请检查就绪处理程序是否已启动。)

    If so, just schedule the newly added callback to fire right after this thread of JS finishes with setTimeout(fn, 1) .

    (如果是这样,只需安排新添加的回调在此JS线程以setTimeout(fn, 1)完成后立即触发。)

  4. If the ready handler has not already fired, then add this new callback to the list of callbacks to be called later.

    (如果就绪处理程序尚未触发,则将此新回调添加到稍后要调用的回调列表中。)

  5. Check if the document is already ready.

    (检查文档是否已经准备好。)

    If so, execute all ready handlers.

    (如果是这样,请执行所有就绪的处理程序。)

  6. If we haven't installed event listeners yet to know when the document becomes ready, then install them now.

    (如果我们尚未安装事件侦听器,但尚不知道文档准备就绪的时间,请立即安装它们。)

  7. If document.addEventListener exists, then install event handlers using .addEventListener() for both "DOMContentLoaded" and "load" events.

    (如果存在document.addEventListener ,则使用.addEventListener()"DOMContentLoaded""load"事件安装事件处理程序。)

    The "load" is a backup event for safety and should not be needed.

    (为了安全起见,“负载”是备用事件,因此不需要。)

  8. If document.addEventListener doesn't exist, then install event handlers using .attachEvent() for "onreadystatechange" and "onload" events.

    (如果document.addEventListener不存在,则使用.attachEvent()安装事件处理程序,以处理"onreadystatechange""onload"事件。)

  9. In the onreadystatechange event, check to see if the document.readyState === "complete" and if so, call a function to fire all the ready handlers.

    (在onreadystatechange事件中,检查document.readyState === "complete" ,如果是,则调用一个函数来激发所有就绪的处理程序。)

  10. In all the other event handlers, call a function to fire all the ready handlers.

    (在所有其他事件处理程序中,调用一个函数以激发所有就绪的处理程序。)

  11. In the function to call all the ready handlers, check a state variable to see if we've already fired.

    (在调用所有就绪处理程序的函数中,检查一个状态变量以查看是否已经解雇了。)

    If we have, do nothing.

    (如果有,什么也不做。)

    If we haven't yet been called, then loop through the array of ready functions and call each one in the order they were added.

    (如果尚未调用,请遍历准备好的函数数组,并按添加顺序调用每个函数。)

    Set

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...