2010-12-20 10 views
30

Testowałem wiele leniwych programów ładujących dla skryptów JavaScript i CSS, które wstawiają znaczniki <skrypt> i <link> do ładowania plików. Problem polega jednak na tym, że znaczniki <link> nie wystrzeliwują onload, więc trudno je wykryć po załadowaniu. Jedynym obejściem tego problemu jest ustawienie display: none; (w pliku CSS, który ma zostać załadowany) na fikcyjnym elemencie i odpytywanie tego elementu w celu sprawdzenia, kiedy zostało ustawione wyświetlanie: brak. Ale to, oprócz brzydoty, działa oczywiście tylko dla pojedynczego pliku CSS.Czy istnieje sposób na wykrycie, kiedy plik CSS został w pełni załadowany?

Więc się zastanawiałem; Czy istnieje inny sposób wykrywania, czy załadowano plik CSS?

+2

Sprawdź to: https://github.com/jAndreas/Supply – jAndy

+0

Miałem nadzieję na rozwiązanie inne niż XHR, więc załadowany plik może być cache i ogólnie to * wydaje się być czystsze, aby dodawać/usuwać pliki zamiast ładować CSS/JS i wstawiać/wykonywać je ... – Lukas

+0

Jest to jedyna niezawodna metoda, której jestem świadomy.Przesyłanie strumieniowe danych do klienta i umieszczanie go w znaczniku 'style'. – jAndy

Odpowiedz

15

edycja: Należy zauważyć, że obsługa przeglądarki dla zdarzeń ładowania na plikach CSS poprawiła się od czasu mojej oryginalnej odpowiedzi. Nie jest to jednak w pełni obsługiwane, więc moja odpowiedź poniżej nadal ma pewne znaczenie. Here is a compatibility chart, nie wiesz jednak, jak ważne jest źródło.

OK, w końcu znalazłem rozwiązanie.

Ten facet http://tugll.tugraz.at/96784/weblog/9080.html wstawia znaczniki link i polls document.styleSheets [index] .rules, dopóki nie jest już niezdefiniowany (gdzie indeks oczywiście jest indeksem nowo wstawionego pliku). Niestety jego kod jest błędny i działa tylko z Safari & FF. Naprawiłem błędy, dodano funkcje Opery i Internet Explorera, a nawet dodałem funkcje do dodawania wielu plików CSS i JS oraz 1 końcowego wywołania zwrotnego (gdy wszystkie pliki są ładowane) w słodkiej i prostej funkcji lazyloadera. Wynik można znaleźć tutaj:

https://github.com/LukasBombach/Lazyloader

3

Edit: (ze względu na możliwe nie wspierają WebKit)

więc wolałbym polecam JQuery LOADER

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

Można spojrzeć na LazyLoad JavaScript biblioteki.

LazyLoad jest mały (tylko 1541 bajtów minified), zależność wolne JavaScript biblioteka, która sprawia, że ​​bardzo łatwo załadować zewnętrzny JavaScript i (nowego w tej wersji) pliki CSS na popytu. Jest idealny do szybkiego i dyskretnego ładowania dużych zewnętrznych skryptów i arkuszy stylów leniwie po zakończeniu ładowania strony lub na żądanie jako potrzebne.

Oprócz obsługi CSS, ta wersja LazyLoad dodaje także obsługę dla równoległego ładowania wielu zasobów w przeglądarkach, które ją obsługują. Aby załadować wielu zasobów w równolegle, po prostu przekazać tablicę adresów w jednym cal LazyLoad

+2

Nie będę polegał na tym: '// Gecko i WebKit nie obsługują zdarzenia onload na węzłach łącza, więc musimy po krótkim czasie zakończyć i mieć nadzieję na najlepsze. – jAndy

+0

Przetestowałem lazyload od wonko. Błyskawicznie uruchamia onload-callback-funtions (zamiast po załadowaniu css), jeśli używasz go z plikami css. – Lukas

+0

@jAndy: Czy to duży problem? Jest tylko jedna linia, która to zmienia;) Jeśli używasz jQuery, możesz użyć yue ..ready() – sv88erik

3

Spróbuj dodać pewną regułę CSS do końca pliku i czekać na CSS należy stosować (check przez JavaScript). Po tym możesz być pewien, że załadowano CSS. Jednak nie mam z tym żadnego doświadczenia. Tylko szybki pomysł może warto spróbować.

+0

Problem polega na tym, że jeśli masz pliki X css, potrzebujesz X różnych reguł css, a to jest bałagan. Musisz także zarządzać wieloma relacjami css-rule css-file <-> i może ci zabraknąć reguł CSS. – Lukas

+0

Zgadzam się z tym. Najwygodniejszym sposobem implementacji tego jest prawdopodobnie napisanie funkcji JS do załadowania pliku CSS. Po określeniu reguł kontrolera po nazwie pliku CSS funkcja JS może ustalić regułę. Nie mam teraz czasu, aby dać ci krótki przykład. –

1

Korzystanie z ładowacza skryptu jak Supply, będzie to wyglądać tak:

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

o "reguł CSS obciążenia sprawdzania":

Jeżeli w Twojej JS skrypt, dołączysz w głowie tag stylu zawierający prostą regułę, jak: #loadingCss {display: block; }

Następnie wystarczy dodać do wszystkich plików CSS coś w stylu: #loadingCss {display: none; }

W nagłówku dokumentu dołączysz znacznik stylu przed tagiem linku. W ten sposób reguła CSS w pliku CSS będzie ważniejsza (ten sam selektor -> ten sam priorytet, ostatni w dokumencie jest zwycięzcą).

Niż w swoim skrypcie JS wystarczy sprawdzić #loadingCss visibility. Gdy wiesz, że Twój plik CSS jest załadowany, możesz usunąć znacznik stylu.

Dla następnego pliku CSS, który chcesz załadować, możesz dodać ten tag stylu ponownie na końcu elementu head.

W ten sposób, za pomocą tylko jednej reguły, można zarządzać załadowaniem wszystkich plików CSS. Jedyny problem z tym rozwiązaniem: nie można załadować więcej niż jednego pliku CSS naraz. Ale jestem pewien, że można znaleźć sposób na zrobienie tego.

Ale tak czy inaczej, nie jestem pewien, czy to rozwiązanie (przy użyciu reguły CSS, aby sprawdzić ładowanie) jest bardzo dobrym rozwiązaniem. Może są inne sposoby, aby to zrobić.

2

Chciałem zaoferować pewien wgląd w to, co może się zmienić.

Zgodnie z jednym z ostatnich akapitów dokumentacji Mozilli <link>, zdarzenie load może być dołączone do elementu link w FF wersji 9 i wyżej oraz Chrome 19 i nowszych. IE i Safari nie są określone. https://developer.mozilla.org/en-US/docs/Web/HTML/Element/link

2

Warto wiedzieć, że teraz aktualne wersje Chrome i Firefox uruchamiają wydarzenie onload w linkach.

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

spróbuj tego: 1- preload css na głowie

<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 - plik js preload na stopce

<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 - przed znacznikiem </body> dodać

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

Testowałem o n firefox 57, chrome 61, yandex, nie testowany na operze i np.

Powiązane problemy