2010-12-20 8 views
30

He estado probando una gran cantidad de cargadores perezosos para JavaScript y CSS que insertan < secuencia de comandos > y < > etiquetas de enlace para cargar archivos. Sin embargo, el problema es que las etiquetas <link> no activan onload, por lo que es difícil detectarlas cuando se cargan. La única solución que encontré para esto es establecer display: none; (en el archivo CSS que se va a cargar) en un elemento ficticio y sondear ese elemento para verificar cuándo se configuró para mostrar: ninguno. Pero eso, además de ser feo, por supuesto, solo funciona para un solo archivo CSS.¿Hay alguna manera de detectar cuándo un archivo CSS se ha cargado por completo?

Así que me preguntaba; ¿Hay alguna otra forma de detectar si se ha cargado un archivo CSS?

+2

Mira esto: https://github.com/jAndreas/Supply – jAndy

+0

Estaba esperando una solución que no sea XHR para que el archivo que cargué pueda ser en caché y en general * se siente * más limpio para agregar/eliminar archivos en lugar de cargar CSS/JS e insertarlo/ejecutarlo ... – Lukas

+0

Es el único método confiable que conozco.Transmitir los datos al cliente y ponerlos en una etiqueta 'style'. – jAndy

Respuesta

15

editar: Cabe señalar que el soporte del navegador para eventos de carga en archivos CSS ha mejorado desde mi respuesta original. Sin embargo, no es totalmente compatible, por lo que mi respuesta a continuación todavía tiene cierta relevancia. Here is a compatibility chart, aunque no estoy seguro de cuán legítima es la fuente.

Bien, finalmente encontré una solución.

Este tipo http://tugll.tugraz.at/96784/weblog/9080.html inserta etiquetas de enlace y encuestas document.styleSheets [index] .rules hasta que ya no esté indefinido (donde el índice del curso es el índice del archivo recién insertado). Desafortunadamente su código tiene errores y solo funciona con Safari & FF. Así que arreglé los errores, agregué funcionalidades para Opera e Internet Explorer e incluso agregué características para agregar múltiples archivos CSS y JS y 1 devolución de llamada final (cuando se cargan todos los archivos) en una función de lazyloader sencilla y dulce. El resultado se puede encontrar aquí:

https://github.com/LukasBombach/Lazyloader

3

Editar: (Debido a la posible no soporta WebKit)

Así que prefiero recomiendan JQuery LOADER

$("a.button, input.button, button.button").Loader(
{ 
    url: [ 
     'core.css', 
     'theme.css', 
     'button.css' 
    ], 
    success: function() { 
     $(this).button(); 
    } 
}); 

Usted puede echar un vistazo a LazyLoad biblioteca JavaScript.

LazyLoad es una pequeña (sólo 1.541 bytes minified), dependencia libre biblioteca JavaScript que hace que sea muy fácil de cargar archivos CSS JavaScript externa y (nuevo en esta versión) en demanda. Es ideal para cargar de forma rápida y discretamente grandes scripts y hojas de estilo externas, ya sea con pereza después de que el resto de la página tiene terminado de cargar o bajo demanda como necesario.

Además del soporte de CSS, esta versión de LazyLoad también agrega soporte para la carga paralela de múltiples recursos en navegadores compatibles. Para cargar múltiples recursos en paralelo, basta con pasar una matriz de direcciones URL en un solo LazyLoad cal

+2

No confiaría en esto: '// Gecko y WebKit no son compatibles con el evento de carga en nodos de enlace, por lo que solo debemos finalizar después de un breve retraso y esperar lo mejor." – jAndy

+0

Probé lazyload de wonko. Dispara instantáneamente las funciones onload-callback (en lugar de cuando el css ha terminado de cargarse) si lo usa con archivos css. – Lukas

+0

@jAndy: ¿Es un gran problema, entonces ?. Solo hay una línea que lo cambia;) Si usas jQuery, puedes usar ... listo() – sv88erik

3

intenta agregar una cierta regla CSS para el final de su archivo y esperar a que el CSS a aplicar (cheque eso a través de JavaScript). Después de eso, puede estar bastante seguro de que el CSS se ha cargado. Sin embargo, no tengo experiencia con eso. Solo una idea rápida puede valer la pena intentarlo.

+0

El problema es que si tiene X archivos CSS, necesita X reglas CSS diferentes, y eso es un desastre. También necesita administrar una gran cantidad de relaciones css-file css-file <-> y es posible que se quede sin reglas CSS. – Lukas

+0

Estoy de acuerdo con eso. La forma más cómoda de implementar esto es escribir una función JS para cargar el archivo CSS. Con las reglas del verificador nombradas después del nombre del archivo CSS, la función JS puede resolver la regla en sí misma. Simplemente no tengo tiempo ahora para darte un pequeño ejemplo. –

1

El uso de un cargador de script como Supply, este sería el resultado:

supply.listen('text/css', function(payload, filename) { 
    switch(filename) { 
     case: 'foo.css': { 
      // do something 
      break; 
     } 
     case: 'baseball.css': { 
      break; 
     } 
     // ... 
    } 
}); 

supply.files({ 
    stylesheet: [ 
     'foo.css', 
     'baseball.css' 
    ] 
}); 

Ref .: SupplyJS

1

Sobre las "reglas CSS carga de comprobación":

Si, en su JS script, anexa en su cabeza una etiqueta de estilo que contiene una regla simple como: #loadingCss {display: block; }

Entonces, solo tiene que agregar en todos sus archivos CSS algo así como: #loadingCss {display: none; }

En el encabezado de su documento, añada la etiqueta de estilo antes de la etiqueta de enlace. De esta manera, la regla CSS en el archivo CSS será más importante (mismo selector -> misma prioridad, el último en el documento es el ganador).

Entonces, en su script JS solo tiene que verificar la visibilidad de #loadingCss. Una vez que sepa que su archivo CSS está cargado, puede eliminar la etiqueta de estilo.

Para el próximo archivo CSS que desea cargar, puede agregar esta etiqueta de estilo nuevamente al final del elemento principal.

De esta manera, con solo una regla, puede administrar todos sus archivos CSS de carga. El único problema con esta solución: no puede cargar más de un archivo CSS a la vez. Pero estoy seguro de que es posible encontrar una manera de hacerlo.

Pero de todos modos, no estoy seguro de que esta solución (utilizando una regla CSS para verificar la carga) sea una muy buena solución. Tal vez hay otras formas de hacer esto.

2

que quería ofrecer una idea de lo que puede haber cambiado.

Según uno de los últimos párrafos en la documentación de Mozilla de <link>, un evento de carga se puede unir a un elemento de enlace en las versiones FF 9 y posteriores, así como Chrome 19 y posteriores. IE y Safari no están indicados. https://developer.mozilla.org/en-US/docs/Web/HTML/Element/link

2

pena saber que ahora versiones actuales de Chrome y Firefox desencadenar el evento onload en los enlaces.

var cssFile = document.createElement("link"); 
cssFile.setAttribute("rel", "stylesheet"); 
cssFile.setAttribute("type", "text/css"); 
// Add event listener 
cssFile.onload = function(){ console.log('loaded'); } 
cssFile.setAttribute("href", 'pathToYour.css'); 
document.getElementsByTagName("head")[0].appendChild(cssFile); 
0

probar esto: 1- precarga css en la cabeza

<link rel="preload" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" as="style" onload="this.rel='stylesheet'"> 
<link rel="preload" href="style.css" as="style" onload="this.rel='stylesheet'"> 

2 - archivo de precarga js en el pie de página

<link rel="preload" as="script" href="https://ajax.googleapis.com/ajax/libs/jquery/2.2.1/jquery.min.js"> 
    <link rel="preload" as="script" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"> 
    <link rel="preload" as="script" href="script.js"> 

3 - antes de añadir la etiqueta </body>

<script>   
/** load defer css - js*/ 
// defer css 
var cssAll = document.querySelectorAll('[as="style"]'); 
for(i = 0; i < cssAll.length; i++){ 
    if(cssAll[i].getAttribute("rel") == "preload"){   
     cssAll[i].setAttribute("rel", "stylesheet"); 
    } 
} 
//defer js 
var jsAll = document.querySelectorAll('[as="script"]'); 
if(!window.jQuery) 
{ 
    // load jquery lib 
    var script = document.createElement('script'); 
    script.type = "text/javascript"; 
    script.src = jsAll[0].getAttribute("href"); 
    document.getElementsByTagName('head')[0].appendChild(script); 
    // load other lib after load jquery 
    script.onload = function() { 
     for(i = 1; i < jsAll.length; i++){ 
      var jsNext = document.createElement('script'); 
      jsNext.type = "text/javascript"; 
      jsNext.src = jsAll[i].getAttribute("href"); 
      document.getElementsByTagName('head')[0].appendChild(jsNext); 
     } 
    } 
} 
</script> 

Probé o n firefox 57, chrome 61, yandex, no probado en opera y es decir

Cuestiones relacionadas