javascript - usar - jquery tag




$(documento) equivalente a.ready sem jQuery (20)

Eu tenho um script que usa $(document).ready , mas não usa mais nada do jQuery. Eu gostaria de aliviar isso removendo a dependência do jQuery.

Como posso implementar minha própria funcionalidade $(document).ready sem usar o jQuery? Eu sei que o uso de window.onload não será o mesmo, pois window.onload acionado depois que todas as imagens, quadros, etc. tiverem sido carregados.


É sempre bom usar equivalentes JavaScript em comparação com jQuery. Uma razão é a dependência de uma biblioteca a menos e eles são muito mais rápidos que os equivalentes da jQuery.

Uma referência fantástica para os equivalentes da jQuery é http://youmightnotneedjquery.com/ .

No que diz respeito à sua pergunta, eu peguei o código abaixo do link acima :) Somente ressalva é que ele só funciona com o Internet Explorer 9+ e posterior.

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

A resposta do jQuery foi bastante útil para mim. Com um pouco de refinação, ajustou bem minhas necessidades. Espero que ajude alguém mais.

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

Basta adicionar isso ao final da sua página HTML ...

<script>
    Your_Function();
</script>

Porque, documentos HTML são analisados ​​pela parte superior.


Coloque seu tag <script>/*JavaScript code*/</script> logo antes do fechamento </body> .

Evidentemente, isso pode não ser adequado para todos, já que requer a alteração do arquivo HTML, em vez de apenas fazer algo no arquivo JavaScript à la document.ready , mas ainda assim ...


Cross-browser (navegadores antigos também) e uma solução simples:

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

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

Mostrando alerta no jsfiddle


Editar:

Aqui está um substituto viável para o jQuery pronto

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

Extraído de https://plainjs.com/javascript/events/running-code-when-the-document-is-ready-15/

Outra boa função domReady aqui tirada de https://.com/a/9899701/175071

Como a resposta aceita estava muito longe de terminar, eu jQuery.ready() função "pronta" como jQuery.ready() base na 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;
})();

Como usar:

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

Não tenho certeza de como esse código é funcional, mas funcionou bem com meus testes superficiais. Isso levou um bom tempo, então espero que você e outros possam se beneficiar disso.

PS .: sugiro compiling lo.

Ou você pode usar http://dustindiaz.com/smallest-domready-ever :

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

ou a função nativa se você precisa apenas suportar os novos navegadores (Ao contrário do jQuery pronto, isso não será executado se você adicionar isso após a página ter sido carregada)

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

Esta pergunta foi feita há muito tempo atrás. Para qualquer um que veja essa questão, agora existe um site chamado "você pode não precisar do jquery", que divide - por nível de suporte ao IE necessário - toda a funcionalidade do jquery e fornece algumas bibliotecas menores e alternativas.

IE8 document script pronto de acordo com você pode não precisar de 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();
        });
}

Eu simplesmente uso:

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

E ao contrário de document.addEventListener("DOMContentLoaded" //etc como na resposta mais importante, ele funciona até o IE9 - http://caniuse.com/#search=DOMContentLoaded indica apenas recentemente como o IE11.

Por exemplo, acesse https://netrenderer.com/index.php , escolha Internet Explorer 9 no menu suspenso, insira https://dexygen.github.io/blog/oct-2017/jekyll/jekyll-categories/liquid-templates/2017/10/22/how-jekyll-builds-site-categories.html e clique em "Render", e você verá algo parecido com a imagem na parte inferior deste post.

Veja o seguinte código Javascript que estou usando no cabeçalho para manipular o estilo do tema "hacker" do Jekyll ao meu gosto - em particular, você pode fazer referência ao bloco if (location.pathname !== rootPath) para ver como estou inserindo os links Home e Blog Home , que estão sendo exibidos pelo IE9 pelo site NetRenderer.

Curiosamente, me deparei com esta solução setTimeout em 2009: está verificando a prontidão do overkill DOM? , o que provavelmente poderia ter sido redigido um pouco melhor, como eu quis dizer com o uso de abordagens mais complicadas de vários frameworks.

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


Existe uma substituição baseada em padrões, DOMContentLoaded que é suportada por mais de 98% dos navegadores , embora não seja o IE8:

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

A função nativa do jQuery é muito mais complicada do que apenas window.onload, como mostrado abaixo.

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

Nós encontramos uma implementação cruzada rápida e suja do nosso navegador que pode fazer o truque para casos mais simples com uma implementação mínima:

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

Recentemente, usei isso para um site para celular. Esta é a versão simplificada de John Resig de "Pro JavaScript Techniques". Depende do 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;
})();

Solução do pobre homem:

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

checkLoad();  

Ver violino

Adicionado este, um pouco melhor eu acho, próprio escopo e não recursivo

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

Ver violino


Três opções:

  1. Se script for a última tag do corpo, o DOM estará pronto antes da execução da tag de script
  2. Quando o DOM estiver pronto, "readyState" mudará para "complete"
  3. Coloque tudo em um ouvinte de evento "DOMContentLoaded"

onreadystatechange

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

Fonte: MDN

DOMContentLoaded

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

Preocupado com navegadores de idade da pedra: Vá para o código fonte do jQuery e use a função ready . Nesse caso você não está analisando + executando toda a biblioteca que você está fazendo apenas uma pequena parte dela.


Vale a pena olhar em AddEvent () Rock Solid e http://www.braksator.com/how-to-make-your-own-jquery .

Aqui está o código no caso do site cair

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

Essa abordagem é a maneira mais curta que posso pensar.

A solução baseada no evento DOMContentLoaded só funciona se o script for carregado antes do documento, enquanto a verificação lenta sugerida aqui garante que o código seja executado sempre, mesmo em scripts carregados dinamicamente mais tarde, exatamente como o documento do JQuery está pronto.

Este código é compatível com todos os navegadores (incluindo alguns legados, até o IE6 e o ​​Safari para Windows).

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

Para o IE9 +:

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

Aqui está o que eu uso, é rápido e cobre todas as bases que eu acho; funciona para tudo, exceto IE <9.

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

Isso parece pegar todos os casos:

  • é acionado imediatamente se o DOM já estiver pronto (se o DOM não estiver "carregando", mas "interativo" ou "completo")
  • se o DOM ainda estiver carregando, ele configurará um ouvinte de evento para quando o DOM estiver disponível (interativo).

O evento DOMContentLoaded está disponível no IE9 e em todo o resto, então, pessoalmente, acho que não há problema em usar isso. Reescreva a declaração da função de seta para uma função anônima regular se você não estiver transpilando seu código do ES2015 para o ES5.

Se você quiser esperar até que todos os ativos sejam carregados, todas as imagens exibidas, etc, use window.onload.


Edite a edição de @duskwuff para também suportar o Internet Explorer 8 . A diferença é uma nova chamada para o teste de função do regex e o setTimeout com uma função anônima.

Além disso, defino o tempo limite para 99.

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

Se você estiver carregando o jQuery perto da parte inferior do BODY, mas estiver tendo problemas com o código que grava jQuery (<func>) ou jQuery (document) .ready (<func>), confira jqShim no Github.

Em vez de recriar sua própria função de prontidão de documento, ele simplesmente mantém as funções até que o jQuery esteja disponível, em seguida, prossegue com o jQuery conforme o esperado. O ponto de mover o jQuery para a parte inferior do corpo é acelerar a carga da página, e você ainda pode realizá-lo, inlining o jqShim.min.js na cabeça do seu modelo.

Eu acabei escrevendo este código para fazer mover todos os scripts no WordPress para o rodapé, e apenas este shim code agora está diretamente no cabeçalho.


Se você não precisa suportar navegadores muito antigos, aqui está uma maneira de fazer isso mesmo quando o script externo é carregado com o atributo assíncrono :

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




jquery