$ (документ). уже эквивалентно без jQuery

1585

У меня есть script, который использует $(document).ready, но он не использует ничего из jQuery. Я хотел бы осветлить его, удалив зависимость jQuery.

Как я могу реализовать свои собственные функции $(document).ready без использования jQuery? Я знаю, что использование window.onload не будет таким же, как window.onload запускается после загрузки всех изображений, кадров и т.д.

  • 293
    ... а также определенно не та же функциональность.
  • 40
    Как говорится в этом ответе , если все, что вам нужно от jQuery - это $(document).ready , вы можете легко решить эту проблему, запустив код в самом низу страницы, а не вверху. HTML5Boilerplate использует именно этот подход.
Показать ещё 2 комментария
Теги:

32 ответа

1149
Лучший ответ

Существует замена на основе стандартов DOMContentLoaded, которая поддерживается более чем 98% браузеров, хотя не IE8:

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

Функция jQuery native намного сложнее, чем просто window.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 );
}
  • 4
    bindReady : github.com/jquery/jquery/blob/master/src/core.js
  • 15
    Реальная работающая простая реализация javascript здесь, если кто-то хочет код, он может просто зайти: stackoverflow.com/questions/9899372/…
Показать ещё 8 комментариев
306

Редактировать:

Здесь жизнеспособная замена для jQuery готова

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

Взято с https://plainjs.com/javascript/events/running-code-when-the-document-is-ready-15/

Еще одна хорошая функция domReady, взятая из https://stackoverflow.com/questions/9899372/pure-javascript-equivalent-of-jquerys-ready-how-to-call-a-function-when-t


Поскольку принятый ответ был очень далек от завершения, я сшил вместе "готовую" функцию, такую как jQuery.ready() на основе источника 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;
})();

Как использовать:

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

Я не уверен, насколько функциональный этот код, но он отлично работал с моими поверхностными тестами. Это заняло довольно много времени, поэтому я надеюсь, что вы и другие можете извлечь из этого выгоду.

PS: Я предлагаю скомпилировать его.

Или вы можете использовать http://dustindiaz.com/smallest-domready-ever:

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

или встроенную функцию, если вам нужно только поддерживать новые браузеры (в отличие от jQuery ready, это не будет работать, если вы добавите это после загрузки страницы)

document.addEventListener('DOMContentLoaded',function(){/*fun code to run*/})
  • 132
    О Боже. Я буду думать много раз, прежде чем удалять зависимость jquery в следующий раз.
  • 22
    @Johnny_D Во-первых, не добавлять зависимость jQuery = Боль ушла!
Показать ещё 12 комментариев
177

Три варианта:

  • Если script - последний тег тела, DOM будет готов до выполнения тега script
  • Когда DOM готов, "readyState" изменится на "complete"
  • Поместите все под прослушиватель событий "DOMContentLoaded"

onreadystatechange

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

Источник: MDN

DOMContentLoaded

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

Обеспокоенный браузерами каменного века: Перейдите в исходный код jQuery и используйте функцию ready. В этом случае вы не разбираетесь и не выполняете всю библиотеку, которую вы делаете, только очень маленькую ее часть.

  • 3
    Этот второй пример гораздо более элегантен и лаконичен, чем отмеченные ответы. Почему этот не был отмечен как правильный?
  • 2
    Еще +1 за вещь DOMContentLoaded, она сделала именно то, что я хотел.
Показать ещё 5 комментариев
77

Поместите свой <script>/*JavaScript code*/</script> вправо перед закрывающим тегом </body>.

По общему признанию, это может не устраивать все цели, поскольку для изменения файла HTML требуется просто изменить файл HTML, а не просто что-то сделать в файле JavaScript a la document.ready, но все же...

  • 0
    Мне кажется, что были проблемы с совместимостью, например, поскольку страница еще не готова, вы не можете делать то или это в этих и тех браузерах. К сожалению, я не могу вспомнить более ясно. Тем не менее, +1 за путь, который достаточно близок в 99% всех случаев (и предложенный Yahoo!).
  • 7
    На самом деле, размещение элемента script внизу страницы - почти идеальное решение. Он работает в кросс-браузерном режиме и имитирует документ. Уже отлично. Единственным недостатком является то, что это (немного) более навязчиво, чем использование какого-либо умного кода, вам нужно будет попросить пользователя создаваемого скрипта добавить дополнительный фрагмент скрипта для вызова вашей функции ready или init.
Показать ещё 3 комментария
64

Бедственное решение:

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

checkLoad();  

Просмотр скрипта

Добавлено это, немного лучше, я думаю, собственный объем и не рекурсивный

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

View Fiddle

  • 0
    Возможно, стоит ограничить рекурсии возрастающей переменной внутри функции.
  • 8
    @PhilipLangford Или просто поместите его в setInterval и полностью удалите рекурсию.
Показать ещё 11 комментариев
30

Я использую это:

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

Примечание. Вероятно, это работает только с более новыми браузерами, особенно такими: http://caniuse.com/#feat=domcontentloaded

  • 13
    IE9 и выше на самом деле
  • 0
    Это также прекрасно работает в скриптах содержимого Chrome Extension, если вы перехватываете событие document_start или document_idle.
19

Действительно, если вас беспокоит Internet 9+, этого кода было бы достаточно, чтобы заменить jQuery.ready:

    document.addEventListener("DOMContentLoaded", callback);

Если вы беспокоитесь о Internet Explorer 6 и некоторых действительно странных и редких браузерах, это будет работать:

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

Этот вопрос задавался довольно давно. Для любого, кто только видит этот вопрос, теперь есть сайт под названием "вам может не понадобиться jquery" , который разбивается - по уровню поддержки IE требуется - все функции jquery и предоставляет некоторые альтернативные, более мелкие библиотеки.

Документ IE8 готов script в соответствии с вам может не понадобиться 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();
        });
}
  • 0
    Интересно, почему необходим 'onreadystatechange' а не document.attachEvent('onload', fn);
13

Недавно я использовал это для мобильного сайта. Это упрощенная версия John Resig от "Pro JavaScript Techniques". Это зависит от 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;
})();
  • 12
    Будьте осторожны с этим кодом. Это НЕ эквивалентно $ (документ) .ready. Этот код запускает обратный вызов, когда document.body готов, что не гарантирует полной загрузки DOM.
11

Ответ jQuery был очень полезен для меня. С небольшим количеством исправлений он хорошо меня удовлетворил. Надеюсь, это поможет кому-то еще.

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 )
}
  • 0
    в некоторых браузерах, removeListener должен вызываться с документом в качестве контекста, т.е. removeListener.call(document, ...
9

Кросс-браузер (старые браузеры тоже) и простое решение:

var docLoaded = setInterval(function () {
    if(document.readyState !== "complete") return;
    clearInterval(docLoaded);

    /*
        Your code goes here i.e. init()
    */
}, 30);

Отображение оповещения в jsfiddle

  • 0
    За исключением случаев, когда загрузка DOM занимает более 30 мс, ваш код не будет выполняться.
  • 0
    @Quelklef это setInterval, а не setTimeout
Показать ещё 1 комментарий
8

Вот наименьший фрагмент кода для проверки готовности DOM, который работает во всех браузерах (даже IE 8):

r(function(){
    alert('DOM Ready!');
});
function r(f){/in/.test(document.readyState)?setTimeout('r('+f+')',9):f()}

Смотрите ответ.

6

Просто добавьте это в нижнюю часть своей HTML-страницы...

<script>
    Your_Function();
</script>

Потому что HTML-документы анализируются верхним дном.

  • 6
    Откуда вы знаете, что DOM создается при выполнении этого кода? В том числе загруженный и проанализированный CSS? API браузера DOMContentLoaded предназначен для этого.
4

Этот кросс-браузерный код вызовет функцию после готовности DOM:

var domReady=function(func){
    var scriptText='('+func+')();';
    var scriptElement=document.createElement('script');
    scriptElement.innerText=scriptText;
    document.body.appendChild(scriptElement);
};

Вот как это работает:

  • Первая строка domReady вызывает метод toString функции, чтобы получить строковое представление функции, которую вы передаете, и обертывает его в выражение, которое сразу вызывает функцию.
  • Остальная часть domReady создает элемент script с выражением и добавляет его в body документа.
  • Браузер запускает теги script, добавленные к body после готовности DOM.

Например, если вы выполните следующее: domReady(function(){alert();});, к элементу body добавится следующее:

 <script>(function (){alert();})();</script>

Обратите внимание, что это работает только для пользовательских функций. Следующие действия не будут работать: domReady(alert);

4

Стоит посмотреть Rock Solid addEvent() и http://www.braksator.com/how-to-make-your-own-jquery.

Вот код, если сайт идет вниз

function addEvent(obj, type, fn) {
    if (obj.addEventListener) {
        obj.addEventListener(type, fn, false);
        EventCache.add(obj, type, fn);
    }
    else if (obj.attachEvent) {
        obj["e"+type+fn] = fn;
        obj[type+fn] = function() { obj["e"+type+fn]( window.event ); }
        obj.attachEvent( "on"+type, obj[type+fn] );
        EventCache.add(obj, type, fn);
    }
    else {
        obj["on"+type] = obj["e"+type+fn];
    }
}

var EventCache = function(){
    var listEvents = [];
    return {
        listEvents : listEvents,
        add : function(node, sEventName, fHandler){
            listEvents.push(arguments);
        },
        flush : function(){
            var i, item;
            for(i = listEvents.length - 1; i >= 0; i = i - 1){
                item = listEvents[i];
                if(item[0].removeEventListener){
                    item[0].removeEventListener(item[1], item[2], item[3]);
                };
                if(item[1].substring(0, 2) != "on"){
                    item[1] = "on" + item[1];
                };
                if(item[0].detachEvent){
                    item[0].detachEvent(item[1], item[2]);
                };
                item[0][item[1]] = null;
            };
        }
    };
}();

// Usage
addEvent(window, 'unload', EventCache.flush);
addEvent(window, 'load', function(){alert("I'm ready");});
3

Я просто использую:

setTimeout(function(){
    //reference/manipulate DOM here
});

И в отличие от document.addEventListener("DOMContentLoaded" //etc, как в самом верхнем ответе, он работает еще в IE9 - http://caniuse.com/#search=DOMContentLoaded указывает только как недавно как IE11.

Например, перейдите в https://netrenderer.com/index.php, выберите Internet Explorer 9 из раскрывающегося списка, введите https://dexygen.github.io/blog/oct-2017/jekyll/jekyll-categories/liquid-templates/2017/10/22/how-jekyll-builds-site-categories.html и нажмите "Render", и вы увидите что-то похожее на скриншот внизу этого сообщения.

См. следующий код Javascript, который я использую в заголовке, чтобы манипулировать стилем темы "Хакер" Jekyll по своему вкусу - в частности, вы можете ссылаться на блок if (location.pathname !== rootPath), чтобы увидеть, как я вставляю Home и Blog Home, которые отображаются IE9 на сайт NetRenderer.

Интересно, что я наткнулся на это решение setTimeout в 2009 году: Проверяет готовность переполнения DOM?, который, вероятно, мог быть сформулирован немного лучше, поскольку Я имел в виду использование более сложных подходов к различным инфраструктурам.

setTimeout(function() {//delay execution until after dom is parsed
    var containerEls = document.getElementsByClassName('container');
    var headingEl = containerEls[0].getElementsByTagName('h1')[0];
    var headerEl = document.getElementsByTagName('header')[0];
    var downloadsSectionEl = document.getElementById('downloads');
    var rootPath = "/";
    var blogRootPath = "/blog/";

    containerEls[0].style.maxWidth = '800px';
    containerEls[1].style.maxWidth = '800px';
    headingEl.style.margin = '0';
    headerEl.style.marginBottom = '7px';
    downloadsSectionEl.style.margin = '0';

    if (location.pathname !== rootPath) {
        downloadsSectionEl.appendChild(generateNavLink('Home', rootPath));
        if (location.pathname !== blogRootPath) {
            downloadsSectionEl.appendChild(document.createTextNode(' | '));
            downloadsSectionEl.appendChild(generateNavLink('Blog Home', blogRootPath));
        }
    }

    function generateNavLink(linkText, hrefPath) {
        var navLink = document.createElement('a');
        var linkTextNode = document.createTextNode(linkText);
        navLink.setAttribute('href', hrefPath);
        navLink.appendChild(linkTextNode);
        return navLink;
    }
});

Изображение 2110

3

Всегда полезно использовать эквиваленты JavaScript по сравнению с jQuery. Одна из причин - это меньшее количество библиотек, которые зависят от них, и они намного быстрее, чем эквиваленты jQuery.

Одна фантастическая ссылка для эквивалентов jQuery http://youmightnotneedjquery.com/.

Что касается вашего вопроса, я взял приведенный ниже код из приведенной выше ссылки:) Только оговорка заключается в том, что он работает только с Internet Explorer 9 и более поздней версией.

function ready(fn) {
    if (document.readyState != 'loading') {
        fn();
    }
    else {
        document.addEventListener('DOMContentLoaded', fn);
    }
}
3

Как насчет этого решения?

// other onload attached earlier
window.onload=function() {
   alert('test');
};

tmpPreviousFunction=window.onload ? window.onload : null;

// our onload function
window.onload=function() {
   alert('another message');

   // execute previous one
   if (tmpPreviousFunction) tmpPreviousFunction();
};
  • 3
    Вы можете использовать addEventListener для окна с «load». Слушатели выполняются один за другим и не нуждаются в цепочке вручную.
  • 1
    Но нагрузка отличается от готовой. «Загрузка» происходит даже до того, как документ «готов». В готовом документе загружен DOM, в загруженном окне DOM не обязательно готов. Хороший ответ, хотя
Показать ещё 3 комментария
2

Представленные здесь решения setTimeout/setInterval будут работать только в определенных обстоятельствах.

Проблема проявляется особенно в старых версиях Internet Explorer до 8.

Переменные, влияющие на успех этих решений setTimeout/setInterval:

1) dynamic or static HTML
2) cached or non cached requests
3) size of the complete HTML document
4) chunked or non chunked transfer encoding

исходный (собственный Javascript) код, разрешающий эту конкретную проблему, находится здесь:

https://github.com/dperini/ContentLoaded
http://javascript.nwbox.com/ContentLoaded (test)

это код, из которого команда jQuery построила свою реализацию.

2

Мы обнаружили, что наша операционная система имеет очень быструю и кропотливую перекрестную версию, которая может сделать трюк для большинства простых случаев с минимальной реализацией:

window.onReady = function onReady(fn){
    document.body ? fn() : setTimeout(function(){ onReady(fn);},50);
};
  • 0
    что такое doc.body !?
1

Если вам не нужно поддерживать очень старые браузеры, вот как это сделать, даже если ваш внешний script загружен атрибутом async:

HTMLDocument.prototype.ready = new Promise(function(resolve) {
   if(document.readyState != "loading")
      resolve();
   else
      document.addEventListener("DOMContentLoaded", function() {
         resolve();
      });
});

document.ready.then(function() {
   console.log("document.ready");
});
1

Вот что я использую, это быстро и охватывает все базы, которые я думаю; работает для всего, кроме IE < 9.

(() => { function fn() {
    // "On document ready" commands:
    console.log(document.readyState);
};  
  if (document.readyState != 'loading') {fn()}
  else {document.addEventListener('DOMContentLoaded', fn)}
})();

Кажется, что это все ломает:

  • срабатывает немедленно, если DOM уже готов (если DOM не "загружается", но "интерактивен" или "завершен" )
  • Если DOM по-прежнему загружается, он устанавливает прослушиватель событий, когда DOM доступен (интерактивный).

Событие DOMContentLoaded доступно в IE9 и во всем остальном, поэтому я лично считаю, что это нормально использовать. Перепишите объявление функции стрелки в обычную анонимную функцию, если вы не переписываете свой код с ES2015 на ES5.

Если вы хотите подождать, пока все активы будут загружены, все изображения будут отображаться и т.д., тогда вместо этого используйте window.onload.

0

Попробуй это:

function ready(callback){
    if(typeof callback === "function"){
        document.addEventListener("DOMContentLoaded", callback);
        window.addEventListener("load", callback);
    }else{
        throw new Error("Sorry, I can not run this!");
    }
}
ready(function(){
    console.log("It worked!");
});
0
function onDocReady(fn){ 
    $d.readyState!=="loading" ? fn():document.addEventListener('DOMContentLoaded',fn);
}

function onWinLoad(fn){
    $d.readyState==="complete") ? fn(): window.addEventListener('load',fn);
} 

onDocReady обеспечивает обратный вызов, когда HTML dom готов к полному доступу/анализу/манипуляции.

onWinLoad обеспечивает обратный вызов, когда все загружено (изображения и т.д.),

  • Эти функции можно вызвать, когда захотите.
  • Поддерживает несколько "слушателей".
  • Будет работать в любом браузере.
0

Этот подход является самым коротким способом, о котором я могу думать.

Решение, основанное на событии DOMContentLoaded, работает только в том случае, если перед документом загружается script, тогда как предложенная здесь ленивая проверка гарантирует, что код выполняется всегда, даже в сценариях, загружаемых динамически позже, точно так же, как документ JQuery готов.

Этот код совместим со всеми браузерами (включая некоторые устаревшие, вплоть до IE6 и Safari для Windows).

(function ready() {
    if (!document.body) {setTimeout(ready, 50); return;}
    // Document is ready here
})();
0

Для IE9 +:

function ready(fn) {
  if (document.readyState != 'loading'){
    fn();
  } else {
    document.addEventListener('DOMContentLoaded', fn);
  }
}
0

Редактирование редактирования @duskwuff для поддержки Internet Explorer 8. Разница - это новый вызов функционального теста регулярного выражения и setTimeout с анонимной функцией.

Кроме того, я установил тайм-аут на 99.

function ready(f){/in/.test(document.readyState)?setTimeout(function(){ready(f);},99):f();}
0

Если вы загружаете jQuery в нижней части BODY, но возникают проблемы с кодом, который записывает jQuery (<func> ) или jQuery (document).ready(<func> ), проверьте jqShim в Github.

Вместо того, чтобы воссоздать свою собственную функцию готовности документа, она просто удерживает функции до тех пор, пока не будет доступна jQuery, а затем продолжит работу с jQuery, как ожидалось. Точка перемещения jQuery в нижней части тела - ускорить загрузку страницы, и вы все равно можете выполнить ее, вставив jqShim.min.js в начало вашего шаблона.

Я закончил тем, что написал этот код, чтобы переместить все сценарии в WordPress в нижний колонтитул, и именно этот код прокладки теперь находится прямо в заголовке.

0

Готовая функция в jQuery делает несколько вещей. Честно говоря, я не вижу, чтобы это заменило его, если у вас не было удивительно небольшой выход с вашего сайта. jQuery - довольно маленькая библиотека, и она обрабатывает все виды кросс-браузера, которые вам понадобятся позже.

Во всяком случае, здесь мало смысла публиковать его, просто откройте jQuery и посмотрите на метод bindReady.

Он начинается с вызова либо document.addEventListener("DOMContentLoaded") либо document.attachEvent('onreadystatechange') зависимости от модели события и продолжается оттуда.

-2

Это было хорошее решение https://stackoverflow.com/questions/799981/document-ready-equivalent-without-jquery. В одном из комментариев рассматривался счетчик для спасения в случае чрезвычайной ситуации. Это моя модификация.

function doTheMagic(counter) {
  alert("It worked on " + counter);
}

// wait for document ready then call handler function
var checkLoad = function(counter) {
  counter++;
  if (document.readyState != "complete" && counter<1000) {
    var fn = function() { checkLoad(counter); };
    setTimeout(fn,10);
  } else doTheMagic(counter);
};
checkLoad(0);
-4

Короче говоря, вместо $(document).ready(), используемого в jQuery, мы можем использовать метод JavaScript:

<script>
    document.addEventListener("DOMContentLoaded", function_name, false);
    function function_name(){
        statements;
    }
</script>

Таким образом, когда страница готова, то есть DOMContentLoaded, тогда будет вызываться функция function_name().

  • 1
    Всякий раз, когда на первой странице появляется вопрос с высоким рейтингом, часто стоит проверить даты, чтобы убедиться, что вы не отвечаете на очень старую публикацию. (Один из сценариев, на который я мог бы ответить, - это если за прошедшие годы появилось новое решение, которого изначально не было. Хотя DOMContentLoaded определенно уже упоминалось.)
-8

Если вы хотите поддерживать Internet Explorer 7+ (никаких причуд, совместимости и другой боли), последний Chrome, последний Safari, последний Firefox и без iframe - этого будет достаточно:

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
  • 10
    Это определенно не Javascript.
  • 8
    Похоже, кто-то пишет CoffeeScript.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню