Câu hỏi $ (tài liệu) .ready tương đương không có jQuery


Tôi có một tập lệnh sử dụng $(document).ready, nhưng nó không sử dụng bất cứ thứ gì khác từ jQuery. Tôi muốn làm sáng nó bằng cách loại bỏ sự phụ thuộc của jQuery.

Làm thế nào tôi có thể thực hiện của riêng tôi $(document).ready chức năng mà không cần sử dụng jQuery? Tôi biết rằng việc sử dụng window.onload sẽ không giống nhau, như window.onload cháy sau khi tất cả các hình ảnh, khung hình, vv đã được tải.


1627
2018-04-28 21:51


gốc


<body onload = "yourFunc ()"> chắc chắn là nhẹ nhất;) - cgp
... và cũng chắc chắn không cùng chức năng. - Joel Mueller
Như câu trả lời này tiểu bang, nếu tất cả những gì bạn muốn từ jQuery là $(document).ready, bạn có thể giải quyết vấn đề đó dễ dàng bằng cách chạy mã của bạn ở cuối trang thay vì ở trên cùng. HTML5Boilerplate sử dụng cách tiếp cận chính xác này. - Blazemonger
Tại sao không chỉ sử dụng DOMContentLoaded? Đó là IE9 + caniuse.com/domcontentloaded  developer.mozilla.org/en-US/docs/Web/Events/DOMContentLoaded - Brock
Tôi đặt cuộc gọi của tôi ở cuối tài liệu và giải quyết vấn đề của tôi. Khi hàm được gọi, mọi thứ sẽ được tải. - IgniteCoders


Các câu trả lời:


Có một tiêu chuẩn dựa trên thay thế,DOMContentLoaded được hỗ trợ bởi hơn 98% trình duyệt, mặc dù không phải IE8:

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

Hàm gốc của jQuery phức tạp hơn nhiều so với window.onload, như được mô tả bên dưới.

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

1053
2018-04-28 21:59



bindReady: github.com/jquery/jquery/blob/master/src/core.js - XP1
Một thực thi javascript đơn giản thực tế ở đây nếu ai đó muốn mã họ có thể chỉ cần thả vào: stackoverflow.com/questions/9899372/… - jfriend00
Mã sẵn sàng jQuery DOM dường như được đơn giản hóa: github.com/jquery/jquery/blob/master/src/core/ready.js - Jose Nobile
Tôi nghĩ rằng tất cả chúng ta đã sẵn sàng để chuyển từ IE8 ...;). Cảm ơn bạn đã liên kết, @JoseNobile. - Con Antonakos
DOMContentLoaded sẽ không hoạt động nếu kịch bản được tải sau đó. Tài liệu JQuery sẵn sàng thực thi luôn. - Jared Insel


Chỉnh sửa:

Đây là một sự thay thế khả thi cho jQuery sẵn sàng

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

Được lấy từ https://plainjs.com/javascript/events/running-code-when-the-document-is-ready-15/


Vì câu trả lời được chấp nhận là rất xa, tôi đã khâu lại với nhau một hàm "sẵn sàng" như jQuery.ready() dựa trên nguồn jQuery 1.6.2:

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

Cách sử dụng:

<script>
    ready(function(){
        alert('It works!');
    });
    ready(function(){
        alert('Also works!');
    });
</script>

Tôi không chắc chắn về chức năng của mã này, nhưng nó hoạt động tốt với các bài kiểm tra bề ngoài của tôi. Việc này mất khá nhiều thời gian, vì vậy tôi hy vọng bạn và những người khác có thể hưởng lợi từ nó.

PS .: Tôi đề nghị biên dịch nó.

Hoặc bạn có thể sử dụng http://dustindiaz.com/smallest-domready-ever:

function r(f){/in/.test(document.readyState)?setTimeout(r,9,f):f()}
r(function(){/*code to run*/});

hoặc chức năng gốc nếu bạn chỉ cần hỗ trợ các trình duyệt mới (Không giống như jQuery sẵn sàng, điều này sẽ không chạy nếu bạn thêm sau khi trang đã tải)

document.addEventListener('DOMContentLoaded',function(){/*fun code to run*/})

290
2017-08-13 20:52



Ôi Chúa ơi. Tôi sẽ suy nghĩ nhiều lần trước khi loại bỏ sự xuất hiện jquery lần sau. - Johnny_D
@Johnny_D Không thêm phụ thuộc jQuery vào vị trí đầu tiên = Đau đã biến mất! - Frederik Krautwald
@FrederikKrautwald không có vấn đề gì mọi người nói, khái niệm jQuery là một điều tốt, bởi vì các API DOM là rất cồng kềnh, tiết và không nhất quán, tôi chỉ muốn có một phiên bản lite đã có sẵn - Timo Huovinen
@TimoHuovinen lựa chọn thay thế: Zepto.js (9.1 kb), Snack.js (8.1 kb), $ dom (2.3 kb) và 140 Medley (0.5 kb). Chỉnh sửa: Bạn cũng có thể xem Ender. - Frederik Krautwald
@FrederikKrautwald $ dom nghe giống như những gì tôi muốn, nhưng không chắc liệu nó có phù hợp với dự luật hay không. Zepto cũng trông rất hứa hẹn, cảm ơn bạn đã chia sẻ! - Timo Huovinen


Ba tùy chọn:

  1. Nếu script là thẻ cuối cùng của nội dung, DOM sẽ sẵn sàng trước khi thực thi thẻ script
  2. Khi DOM sẵn sàng, "readyState" sẽ thay đổi thành "hoàn thành"
  3. Đặt mọi thứ trong trình nghe sự kiện 'DOMContentLoaded'

onreadystatechange

  document.onreadystatechange = function () {
     if (document.readyState == "complete") {
     // document is ready. Do your stuff here
   }
 }

Nguồn: MDN

Đã tải DOMContentLoaded

document.addEventListener('DOMContentLoaded', function() {
   console.log('document is ready. I can sleep now');
});

Lo ngại về các trình duyệt thời kỳ đồ đá: Đi đến mã nguồn jQuery và sử dụng ready chức năng. Trong trường hợp đó bạn không phân tích cú pháp + thực hiện toàn bộ thư viện bạn đang làm chỉ một phần rất nhỏ của nó.


184
2017-09-12 22:33



Ví dụ thứ hai này là nhiều hơn nữa thanh lịch và ngắn gọn hơn so với câu trả lời được đánh dấu. Tại sao cái này không được đánh dấu đúng? - 0112
Vẫn +1 cho điều DOMContentLoaded, nó đã làm chính xác những gì tôi muốn. - tripleee
onreadystatechange đã làm các trick cho tôi ... cần thiết để chạy một số kịch bản sau khi tải async jquery. - Abram
Cũng giống như một FYI, # 1 không hoàn toàn đúng. Nó hoàn toàn có thể cho một kịch bản ở cuối trang để tải trước khi DOM được thực hiện. Đó là lý do tại sao người nghe cao hơn. Họ lắng nghe khi trình duyệt được thực hiện. Đặt nó ở cuối là vượt qua ngón tay của bạn mà tải kịch bản chậm hơn trình duyệt có thể hiển thị. - Machavity
biến thể này cũng sẽ hoạt động khi tài liệu đã được tải xong, vui lòng cập nhật câu trả lời (tốt nhất) của bạn nếu bạn có thể: if (document.readyState == 'complete') {init (); } else {document.onreadystatechange = function () {if (document.readyState == 'complete') {init (); }}} - ZPiDER


Đặt địa điểm của bạn <script>/*JavaScript code*/</script> đúng trước khi đóng  </body> nhãn.

Phải thừa nhận rằng, điều này có thể không phù hợp với mục đích của mọi người vì nó đòi hỏi phải thay đổi tệp HTML thay vì chỉ làm điều gì đó trong tệp JavaScript a la document.ready, nhưng vẫn...


81
2017-12-07 16:46



Dường như với tôi rằng có các vấn đề tương thích, như, vì trang chưa sẵn sàng, bạn không thể làm điều này hoặc trong các trình duyệt này và các trình duyệt đó. Đáng tiếc là tôi không thể nhớ rõ hơn. Tuy nhiên, 1 cho một cách là đủ gần trong 99% của tất cả các trường hợp (và được đề xuất bởi Yahoo). - Boldewyn
Trên thực tế, việc đặt phần tử tập lệnh ở cuối trang là một giải pháp gần như hoàn hảo. Nó hoạt động qua trình duyệt và mô phỏng document.ready hoàn hảo. Nhược điểm duy nhất là nó hơi khó chịu hơn việc sử dụng một số mã thông minh, bạn sẽ phải hỏi người dùng kịch bản mà bạn đang tạo để thêm một đoạn mã phụ để gọi hàm sẵn sàng hoặc init của bạn. - Stijn de Witt
@StijndeWitt - Bạn có ý nghĩa gì về việc phải gọi một hàm init? Một kịch bản sử dụng document.ready không cần mã máy khách khác để gọi nó, nó là khép kín, và tương đương với đoạn mã được bao gồm ở cuối thân thể cũng có thể được khép kín và không yêu cầu mã khác để gọi nó. - nnnnnn
Tại sao không đặt kịch bản sau thẻ body đóng và trước khi đóng </html> nhãn? - Charles Holbrow


Giải pháp của người nghèo:

var checkLoad = function() {   
    document.readyState !== "complete" ? setTimeout(checkLoad, 11) : alert("loaded!");   
};  

checkLoad();  

Xem Fiddle

Thêm cái này, tốt hơn một chút tôi đoán, phạm vi của riêng, và không đệ quy

(function(){
    var tId = setInterval(function() {
        if (document.readyState == "complete") onComplete()
    }, 11);
    function onComplete(){
        clearInterval(tId);    
        alert("loaded!");    
    };
})()

Xem Fiddle


67
2017-08-04 18:13



@PhilipLangford Hoặc chỉ cần đặt nó bên trong một setInterval và loại bỏ hoàn toàn đệ quy. - Alex W
@ Raveren, hmm bạn nói đúng, tôi khá chắc chắn tôi đã thử nghiệm nó khi tôi đăng nó. Dù sao, nó chỉ trở nên đơn giản hơn, bây giờ hàm chỉ được gọi, không gói. - Jakob Sternberg
Đây không phải là sexy. Không xin lỗi. Sử dụng bộ tính giờ / khoảng thời gian để phát hiện các công cụ có thể "hoạt động" nhưng nếu bạn tiếp tục lập trình như thế này thì bất kỳ dự án lớn hơn nào có giá trị muối của nó sẽ lặn. Đừng hack cùng nhau như thế này. Làm đúng. Xin vui lòng. Loại mã này làm tổn thương hệ sinh thái phát triển bởi vì có một giải pháp tốt hơn và bạn BIẾT nó. - dudewad
Tôi nghĩ câu trả lời này gần hơn với dustindiaz.com/smallest-domready-ever Vì vậy, tôi đã cải thiện tập lệnh: jsfiddle.net/iegik/PT7x9 - iegik
@ReidBlomquist Có, và đây là một cách "sai", và đó là những gì tôi chỉ ra (mặc dù một chút adamantly, tôi biết). Bạn có thể nói rằng bằng cách làm sai nó là bằng cách nào đó "giúp" hệ sinh thái, nhưng vấn đề là với số lượng mã xấu ra khỏi đó mà mọi người lấy cho "tốt" mã bởi vì họ không có kinh nghiệm để biết bất kỳ tốt hơn KHÔNG giúp hệ sinh thái, bởi vì sau đó họ sẽ lấy mã xấu đó và thực hiện nó thành một giải pháp kiến ​​trúc sản xuất thực tế. Vì vậy, tôi đoán, chúng tôi sẽ chỉ phải khác biệt về ý kiến ​​"sai lầm" này. - dudewad


Tôi sử dụng điều này:

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

Lưu ý: Điều này có thể chỉ hoạt động với các trình duyệt mới hơn, đặc biệt là các trình duyệt sau: http://caniuse.com/#feat=domcontentloaded


31
2017-12-23 19:14



IE9 và trên thực tế - Pascalius


Thực sự, nếu bạn quan tâm Internet Explorer 9+ chỉ, mã này sẽ đủ để thay thế jQuery.ready:

    document.addEventListener("DOMContentLoaded", callback);

Nếu bạn lo lắng về Internet Explorer 6 và một số trình duyệt thực sự lạ và hiếm, điều này sẽ hoạt động:

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

19
2017-11-07 07:45





Câu hỏi này đã được hỏi khá lâu rồi. Đối với bất cứ ai chỉ nhìn thấy câu hỏi này, bây giờ có một trang web được gọi là "bạn có thể không cần jquery"  bị phá vỡ - theo mức độ hỗ trợ của IE được yêu cầu - tất cả các chức năng của jquery và cung cấp một số thư viện thay thế, nhỏ hơn.

Tập lệnh sẵn sàng cho tài liệu IE8 theo bạn có thể không cần jquery

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

15
2018-02-16 14:15



Tôi tự hỏi tại sao 'onreadystatechange' là cần thiết hơn là document.attachEvent('onload', fn); - Luke


Gần đây, tôi đã sử dụng trang này cho trang web dành cho thiết bị di động. Đây là phiên bản đơn giản của John Resig từ "Kỹ thuật JavaScript Pro". Nó phụ thuộc vào 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;
})();

13
2017-09-22 01:29



Hãy cẩn thận với mã này. Nó KHÔNG tương đương với $ (tài liệu). Mã này kích hoạt gọi lại khi document.body sẵn sàng không đảm bảo DOM được nạp đầy đủ. - Karolis


Câu trả lời jQuery khá hữu ích đối với tôi. Với một chút tinh luyện, nó đáp ứng nhu cầu của tôi tốt. Tôi hy vọng nó sẽ giúp bất cứ ai khác.

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
2017-09-05 16:56



trên một số trình duyệt, removeListener sẽ cần phải được gọi với tài liệu như bối cảnh, tức là. removeListener.call(document, ... - Ron