javascript - чистом - window onload js




$(document). уже эквивалент без jQuery (20)

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

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


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

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

Посмотреть скрипт


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

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

См. Этот answer .


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

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

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

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

Действительно, если вы заботитесь только об Internet Explorer 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();
        }
    }
},

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

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

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

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


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

window.onReady = function onReady(fn){
    document.body ? fn() : setTimeout(function(){ onReady(fn);},50);
};

Ответ 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 )
}

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

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


Представленные здесь решения 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 построила свою реализацию.


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

<script>
    Your_Function();
</script>

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


Стоит посмотреть в 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");});

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

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

Собственная функция jQuery намного сложнее, чем просто 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 );
}

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

Для сценария, подготовленного для документа IE8, по вашему желанию может не понадобиться 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();
        });
}

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

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

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

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

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

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

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


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

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

И в отличие от document.addEventListener("DOMContentLoaded" //etc Как в самом 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;
    }
});


Для IE9 +:

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

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

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

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


Если вам не нужно поддерживать очень старые браузеры, вот как это сделать, даже если ваш внешний скрипт загружен атрибутом 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");
});

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

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

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

Это было хорошее решение https://.com/a/11810957/185565 бедных. В одном из комментариев рассматривался счетчик для спасения в случае чрезвычайной ситуации. Это моя модификация.

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






jquery