Dodawanie elementów interaktywnych za pomocą JavaScriptu

Data publikacji: 31 grudnia 2013 r.

Dzięki JavaScript możemy modyfikować niemal każdy aspekt strony: treść, styl i reakcje na interakcje użytkownika. JavaScript może też jednak blokuj konstrukcję DOM i opóźniaj renderowanie strony. Aby zapewnić optymalną wydajność, użyj asynchronicznego JavaScriptu i usuń z krytycznej ścieżki renderowania wszystkie zbędne elementy JavaScriptu.

Podsumowanie

  • JavaScript może wysyłać zapytania i modyfikować DOM oraz CSSOM.
  • Bloki wykonywania JavaScriptu w CSSOM.
  • JavaScript blokuje tworzenie DOM, chyba że jest wyraźnie zadeklarowany jako asynchroniczny.

JavaScript to dynamiczny język, który działa w przeglądarce i umożliwia zmianę niemal każdego aspektu zachowania strony: możemy modyfikować treść, dodając elementy do drzewa DOM lub je z niego usuwając. możemy modyfikować właściwości CSSOM każdego elementu, możemy obsłużyć dane wejściowe użytkownika, i wiele innych. Aby to zilustrować, zobacz, co się dzieje, gdy poprzedni przykład „Hello World” zostanie zmieniony tak, aby zawierał krótki skrypt wbudowany:

<!DOCTYPE html>
<html>
  <head>
    <meta name="viewport" content="width=device-width,initial-scale=1" />
    <link href="style.css" rel="stylesheet" />
    <title>Critical Path: Script</title>
  </head>
  <body>
    <p>Hello <span>web performance</span> students!</p>
    <div><img src="awesome-photo.jpg" /></div>
    <script>
      var span = document.getElementsByTagName('span')[0];
      span.textContent = 'interactive'; // change DOM text content
      span.style.display = 'inline'; // change CSSOM property
      // create a new element, style it, and append it to the DOM
      var loadTime = document.createElement('div');
      loadTime.textContent = 'You loaded this page on: ' + new Date();
      loadTime.style.color = 'blue';
      document.body.appendChild(loadTime);
    </script>
  </body>
</html>

Wypróbuj

  • Dzięki JavaScriptowi możemy uzyskać dostęp do modelu DOM i wyodrębnić odwołanie do ukrytego węzła span. Węzeł może nie być widoczny w drzewie renderowania, ale nadal jest obecny w modelu DOM. Następnie, gdy mamy odniesienie, możemy zmienić jego tekst (za pomocą .textContent), a nawet zastąpić obliczoną właściwość stylu wyświetlania z „none” (brak). do tekstu „inline”. Teraz na stronie wyświetla się komunikat „Cześć, interaktywni uczniowie”.

  • Dzięki JavaScriptowi możemy też tworzyć, stylizować, dołączać i usuwać nowe elementy w modelu DOM. Technicznie rzecz biorąc, cała strona może być tylko jednym dużym plikiem JavaScript, który tworzy i określa style poszczególnych elementów. Mimo że to zadziała, w praktyce używanie HTML i CSS jest znacznie łatwiejsze. W drugiej części funkcji JavaScript tworzymy nowy element div, ustawiamy jego treść tekstową, określamy jego styl i dodajemy go do treści.

Podgląd strony wyrenderowanej na urządzeniu mobilnym.

Zmieniliśmy treść i styl CSS dotychczasowego węzła DOM oraz dodaliśmy do dokumentu zupełnie nowy węzeł. Nasza strona nie zdobędzie nagród za design, ale pokazuje, jak dużą moc i elastyczność daje nam JavaScript.

Mimo że JavaScript daje nam mnóstwo możliwości, nakłada wiele dodatkowych ograniczeń w sposobie i czasie renderowania strony.

Po pierwsze, zwróć uwagę na to, że w poprzednim przykładzie nasz wbudowany skrypt znajduje się u dołu strony. Dlaczego? Spróbuj samodzielnie wykonać ten krok, ale jeśli przeniesiemy skrypt nad element <span>, zauważysz, że skrypt nie działa i narzeka, że nie może znaleźć odniesienia do żadnego elementu <span> w dokumencie; czyli getElementsByTagName('span') zwraca null. Pokazuje to ważną właściwość: nasz skrypt jest wykonywany dokładnie w miejscu, w którym został wstawiony w dokumencie. Gdy parser HTML napotyka tag skryptu, wstrzymuje proces konstruowania modelu DOM i przekazuje kontrolę mechanizmowi JavaScript. po zakończeniu działania silnika JavaScriptu przeglądarka wznowi działanie od miejsca, w którym została przerwana, i wznawia budowę DOM.

Inaczej mówiąc, nasz blok skryptu nie może znaleźć żadnych elementów w dalszej części strony, ponieważ nie zostały one jeszcze przetworzone. Albo inaczej: wykonanie wbudowanego skryptu blokuje konstrukcję DOM, co opóźnia początkowe renderowanie.

Inną subtelną właściwością wprowadzania skryptów na stronie jest to, że mogą one odczytywać i modyfikować nie tylko DOM, ale również właściwości CSSOM. Właśnie to robimy w tym przykładzie, gdy zmieniamy właściwość wyświetlania elementu span z brak na „wbudowany”. Jaki jest efekt końcowy? Mamy teraz warunki do wyścigu.

Co się stanie, jeśli w momencie, gdy chcemy uruchomić skrypt, przeglądarka nie skończy pobierania i tworzenia obiektu CSSOM? Odpowiedź nie jest korzystna dla wydajności: przeglądarka opóźnia wykonanie skryptu i tworzenie elementu DOM, dopóki nie zakończy pobierania i tworzenia elementu CSSOM.

Krótko mówiąc, JavaScript wprowadza wiele nowych zależności między DOM, CSSOM i wykonaniem JavaScriptu. Może to spowodować znaczne opóźnienia w przetwarzaniu i renderowaniu strony na ekranie przez przeglądarkę:

  • Lokalizacja skryptu w dokumencie ma znaczenie.
  • Gdy przeglądarka napotka tag skryptu, tworzenie elementu DOM zostaje wstrzymane do czasu zakończenia działania skryptu.
  • JavaScript może wysyłać zapytania i modyfikować DOM oraz CSSOM.
  • Wykonywanie kodu JavaScript zostanie wstrzymane, dopóki CSSOM nie będzie gotowy.

„Optymalizowanie ścieżki renderowania krytycznych elementów” oznacza w dużej mierze zrozumienie i zoptymalizowanie grafu zależności między HTML, CSS i JavaScriptem.

Blokowanie parsera a asynchroniczny JavaScript

Domyślnie wykonywanie JavaScriptu to „blokowanie parsera” – gdy przeglądarka napotka skrypt w dokumencie, musi wstrzymać konstrukcję DOM, przekazać kontrolę nad środowiskiem wykonawczym JavaScript i poczekać, aż skrypt zostanie wykonany, zanim będzie można kontynuować budowę DOM. W poprzednim przykładzie pokazaliśmy to w przypadku skryptu wbudowanego. W rzeczywistości skrypty wbudowane zawsze blokują parser, chyba że napiszesz dodatkowy kod, który opóźni ich wykonanie.

A co ze skryptami dołączonymi do tagu skryptu? Weź poprzedni przykład i wyodrębnij kod do oddzielnego pliku:

<!DOCTYPE html>
<html>
  <head>
    <meta name="viewport" content="width=device-width,initial-scale=1" />
    <link href="style.css" rel="stylesheet" />
    <title>Critical Path: Script External</title>
  </head>
  <body>
    <p>Hello <span>web performance</span> students!</p>
    <div><img src="awesome-photo.jpg" /></div>
    <script src="app.js"></script>
  </body>
</html>

app.js

var span = document.getElementsByTagName('span')[0];
span.textContent = 'interactive'; // change DOM text content
span.style.display = 'inline'; // change CSSOM property
// create a new element, style it, and append it to the DOM
var loadTime = document.createElement('div');
loadTime.textContent = 'You loaded this page on: ' + new Date();
loadTime.style.color = 'blue';
document.body.appendChild(loadTime);

Wypróbuj

Czy używamy tagu <script> lub wbudowany fragment kodu JavaScript, mogą działać w ten sam sposób. W obu przypadkach przeglądarka wstrzymuje działanie, uruchamia skrypt, zanim przetworzy pozostałą część dokumentu. W przypadku zewnętrznego pliku JavaScript przeglądarka musi jednak zatrzymać się na oczekiwanie na pobranie skryptu z dysku, pamięci podręcznej lub serwera zdalnego, może wydłużyć czas renderowania krytycznego o dziesiątki do tysięcy milisekund ścieżki konwersji.

Domyślnie cały kod JavaScript jest blokowany przez parsowanie. Ponieważ przeglądarka nie wie, co skrypt zamierza zrobić na stronie, zakłada najgorszy scenariusz i blokuje parsowanie. Sygnał dla przeglądarki, że nie trzeba wykonywać skryptu w dokładnie takim miejscu, w którym się odwołuje, przeglądarka może kontynuować tworzenie modelu DOM i umożliwić wykonanie skryptu, gdy będzie gotowy. na przykład po pobraniu pliku z pamięci podręcznej lub serwera zdalnego.

Aby to osiągnąć, do elementu <script> dodawany jest atrybut async:

<!DOCTYPE html>
<html>
  <head>
    <meta name="viewport" content="width=device-width,initial-scale=1" />
    <link href="style.css" rel="stylesheet" />
    <title>Critical Path: Script Async</title>
  </head>
  <body>
    <p>Hello <span>web performance</span> students!</p>
    <div><img src="awesome-photo.jpg" /></div>
    <script src="app.js" async></script>
  </body>
</html>

Wypróbuj

Dodanie słowa kluczowego asynchronicznego do tagu skryptu informuje przeglądarkę, aby nie blokowała konstrukcji DOM podczas oczekiwania na udostępnienie skryptu, co może znacznie zwiększyć wydajność.

Prześlij opinię