Nowoczesna przeglądarka internetowa (część 4)

Mariko Kosaka

Dane wejściowe trafią do kompozytora

To ostatnia część z 4 członków naszej serii poświęconej Chrome. jak działa, nasz kod do wyświetlenia witryny. W poprzednim poście przyglądaliśmy się procesowi renderowania i znajdowaliśmy kompozytor. W tym poście omówimy zobaczysz, jak kompozytor umożliwia płynną interakcję po otrzymaniu danych wejściowych użytkownika.

Wprowadzanie zdarzeń z perspektywy przeglądarki

Gdy usłyszysz „Zdarzenia wejściowe” że możemy napisać coś w polu tekstowym lub kliknąć myszą, z perspektywy przeglądarki, dane wejściowe oznaczają dowolny gest użytkownika. Przewijanie kółkiem myszy to wprowadzanie danych zdarzenie oraz dotknięcie lub najechanie myszą również zostanie zdarzeniem wejściowym.

Gdy następuje gest użytkownika taki jak dotknięcie ekranu, to proces przeglądarki otrzymuje gest: Przeglądarka wie jednak tylko, gdzie miała miejsce gest, ponieważ treść na karcie jest obsługiwana przez mechanizm renderowania. Proces przeglądarki wysyła więc zdarzenie (np. touchstart) i jego współrzędne do procesu renderowania. Mechanizm renderowania obsługuje odpowiednie zdarzenie, znajdując cel zdarzenia i uruchomione detektory zdarzeń.

zdarzenie wejściowe
Rysunek 1. Zdarzenie wejściowe kierowane przez proces przeglądarki do procesu renderowania

Kompozytor odbiera zdarzenia wejściowe

Rysunek 2: Widoczny obszar nad warstwami strony

W poprzednim poście pokazaliśmy, jak kompozytor może płynnie obsługiwać przewijanie przez zrasteryzowanych warstw. Jeśli do strony nie są podłączone żadne detektory zdarzeń wejściowych, wątek kompozytora może aby utworzyć nową ramkę kompozytową całkowicie niezależną od wątku głównego. Ale co, jeśli jakieś zdarzenie do strony dodano słuchaczy? Jak wątek kompozytora może sprawdzić, czy zdarzenie wymaga zająć się sprawą?

Omówienie regionu z możliwością przewijania

Uruchamianie JavaScriptu jest zadaniem wątku głównego, więc gdy strona jest skomponowana, wątek kompozytora oznacza region strony, który zawiera moduły obsługi zdarzeń dołączone jako „Region nieprzewijany bez szybkości przewijania”. Według gdy ta informacja jest dostępna, wątek kompozytora może wysyłać zdarzenie wejściowe do wątku głównego. jeśli zdarzenie ma miejsce w danym regionie. Jeśli zdarzenie wejściowe pochodzi spoza tego regionu, wątek kompozytora kontynuuje komponowanie nowej ramki bez oczekiwania na wątek główny.

ograniczony region bez możliwości szybkiego przewijania
Rysunek 3. Schemat opisanego wprowadzania danych do obszaru z możliwością przewijania, którego nie można szybko przewijać

Zachowaj ostrożność podczas pisania modułów obsługi zdarzeń

Typowym wzorcem obsługi zdarzeń w programowaniu stron internetowych jest przekazywanie zdarzeń. Od początku wydarzeń może dołączać 1 moduł obsługi zdarzeń u góry elementu i przekazywać zadania na podstawie celu zdarzenia. Ty mogło zobaczyć lub napisać kod podobny do tego poniżej.

document.body.addEventListener('touchstart', event => {
    if (event.target === area) {
        event.preventDefault();
    }
});

Ponieważ wystarczy napisać jeden moduł obsługi zdarzeń dla wszystkich elementów, ergonomia tego zdarzenia jest atrakcyjny dla użytkowników. Jeśli jednak spojrzysz na ten kod z punktu widzenia przeglądarki , teraz cała strona jest oznaczona jako obszar, którego nie można szybko przewijać. Oznacza to, że nawet wtedy, gdy nie dba o dane wejściowe z określonych części strony, wątek kompozytora musi komunikują się z wątkiem głównym i czekają na niego za każdym razem, gdy pojawi się zdarzenie wejściowe. Dlatego funkcja płynnego przewijania w przypadku kompozytora jest tracona.

cały obszar strony bez możliwości szybkiego przewijania
Rysunek 4. Schemat opisywanego wprowadzania danych do obszaru z możliwością przewijania nieszybkiego przewijania na całej stronie

Aby temu zapobiec, możesz przekazać w wydarzeniu opcje passive: true słuchacz. Ten komunikat informuje przeglądarkę, że nadal chcesz nasłuchiwać zdarzenia w wątku głównym, ale kompozytor może też przejść dalej i skomponować nową ramkę.

document.body.addEventListener('touchstart', event => {
    if (event.target === area) {
        event.preventDefault()
    }
 }, {passive: true});

Sprawdź, czy można anulować wydarzenie

przewinięcie strony
Rysunek 5. Strona internetowa z częścią przy przewijaniu w poziomie

Załóżmy, że masz pole na stronie, w którym chcesz ograniczyć kierunek przewijania tylko do przewijania w poziomie.

Użycie opcji passive: true w zdarzeniu wskaźnika sprawia, że przewijanie strony może być płynne, przewijanie w pionie mogło rozpocząć się przed preventDefault, by ograniczyć kierunek przewijania. Możesz to sprawdzić, używając metody event.cancelable.

document.body.addEventListener('pointermove', event => {
    if (event.cancelable) {
        event.preventDefault(); // block the native scroll
        /*
        *  do what you want the application to do here
        */
    }
}, {passive: true});

Możesz też użyć reguły CSS, takiej jak touch-action, by całkowicie wyeliminować moduł obsługi zdarzeń.

#area {
  touch-action: pan-x;
}

Znajdowanie celu zdarzenia

test wyników
Rysunek 6. Wątek główny patrzący na zapisy malowania z pytaniem, co jest narysowane w punkcie x.y

Gdy wątek kompozytora wysyła zdarzenie wejściowe do wątku głównego, pierwszym uruchomieniem jest działanie aby znaleźć cel zdarzenia. Test trafień wykorzystuje dane z rejestrów renderowania, które zostały wygenerowane podczas renderowania aby ustalić, co znajduje się pod współrzędnymi punktu, w którym doszło do zdarzenia.

Minimalizowanie wysyłania zdarzeń do wątku głównego

W poprzednim poście omówiliśmy, jak nasz typowy wyświetlacz odświeża ekran 60 razy na sekundę. na zachowanie tempa i płynności animacji. Do wprowadzania danych typowy ekran dotykowy urządzenie generuje zdarzenie dotknięcia 60–120 razy na sekundę, a typowa mysz – 100 razy sekunda. Zdarzenie wejściowe ma wyższą dokładność, niż można odświeżyć ekran.

Jeśli zdarzenie ciągłe, takie jak touchmove, zostało wysłane do wątku głównego 120 razy na sekundę, może wywołać nadmierną liczbę testów trafień i wykonania JavaScriptu w porównaniu do czasu może odświeżyć ekran.

niefiltrowane zdarzenia
Rysunek 7. Zdarzenia zapełniające oś czasu ramki, powodujące zacinanie się strony

Aby zminimalizować liczbę wywołań wątku głównego, Chrome łączy zdarzenia ciągłe (takie jak wheel, mousewheel, mousemove, pointermove, touchmove) i opóźnienia w wysyłce do tuż przed następnym requestAnimationFrame.

wydarzenia łączone
Rysunek 8. Ten sam harmonogram co wcześniej, ale wydarzenie jest łączone i opóźnione

Dowolne zdarzenia, takie jak keydown, keyup, mouseup, mousedown, touchstart i touchend są wysyłane natychmiast.

Użyj getCoalescedEvents, aby pobrać zdarzenia w ramce

W przypadku większości aplikacji internetowych połączone zdarzenia powinny zapewniać dobre wrażenia użytkowników. Jeśli jednak tworzysz np. aplikację do rysowania i umieszczasz ścieżkę na podstawie touchmove. Aby narysować gładką linię, między współrzędnymi mogą zostać utracone obszary. W takim przypadku możesz użyć metody getCoalescedEvents w zdarzeniu wskaźnika, aby uzyskać informacje o tych powiązane wydarzenia.

getCoalescedEvents
Rysunek 9. Po lewej stronie scalona ograniczona ścieżka gestu płynnego dotyku po prawej
window.addEventListener('pointermove', event => {
    const events = event.getCoalescedEvents();
    for (let event of events) {
        const x = event.pageX;
        const y = event.pageY;
        // draw a line using x and y coordinates.
    }
});

Dalsze kroki

W tej serii omówiliśmy wewnętrzne działanie przeglądarki. Jeśli nigdy nie zastanawiasz się, dlaczego Narzędzia deweloperskie zalecają dodanie elementu {passive: true} do modułu obsługi zdarzeń lub powodzenie, dla którego warto wpisać async w tagu skryptu, mam nadzieję, że ta seria pomoże Ci wyjaśnić, dlaczego przeglądarka aby zapewnić szybsze i płynniejsze korzystanie z internetu.

Użyj narzędzia Lighthouse

Jeśli chcesz, aby kod działał dobrze w przeglądarce, ale nie wiesz, od czego zacząć, Lighthouse to narzędzie do przeprowadzania audytu każdej strony internetowej tworzyć raporty dotyczące tego, co zostało zrobione dobrze, a co wymaga poprawy. Czytanie listy kontroli pokazuje też, co jest ważne dla przeglądarki.

Dowiedz się, jak mierzyć skuteczność

Poprawa wydajności może się różnić w zależności od witryny, dlatego ważne jest, aby mierzyć jej skuteczność. i zdecyduj, co jest dla niej najlepsze. Zespół Narzędzi deweloperskich w Chrome ma kilka samouczków na temat jak mierzyć skuteczność witryny.

Dodawanie zasad dotyczących funkcji do witryny

Jeśli chcesz zrobić coś dodatkowego, zapoznaj się z Zasadami dotyczącymi funkcji funkcja platformy internetowej, która może stanowić barierę przy tworzeniu projektu. Włączam zasady dotyczące funkcji gwarantują określone działanie aplikacji i zapobiegają popełnieniu błędów. Jeśli na przykład chcesz mieć pewność, że aplikacja nigdy nie będzie blokowała analizy, możesz ją uruchomić zasady skryptów synchronicznych. Gdy zasada sync-script: 'none' jest włączona, kod JavaScript blokujący parser nie można zrealizować. Zapobiega to blokowaniu parsera w kodzie, a tag nie musi się martwić wstrzymywaniem parsera.

Podsumowanie

dziękuję

Gdy zaczęłam tworzyć witryny, zależało mi tylko na tym, jak pisałem kod i co pomogłoby mi zwiększyć produktywność. To ważne, ale powinniśmy też zastanowić się, pobiera napisany przez nas kod. Nowoczesne przeglądarki nieustannie inwestują w sposoby i zapewnić użytkownikom lepsze wrażenia z korzystania z internetu. Dzięki uprzejmości względem przeglądarki przez organizację kodu z kolei poprawia wrażenia użytkownika. Mam nadzieję, że weźmiesz udział w tej misji i bawię się dobrze dla przeglądarek.

Serdecznie dziękujemy wszystkim, którzy przeglądali wczesne wersje robocze tej serii, w tym (ale nie tylko do): Alex Russell, Paul Ireland Meggin Kearney Eric Bidelman, Mathias Bynens Addy Osmani Kinuko Yasuda Nasko Oskov, i Charlie Reis.

Podobała Ci się ta seria? Jeśli masz jakieś pytania lub sugestie związane z kolejnym postem, Chętnie poznam Twoją opinię w sekcji komentarzy poniżej lub na koncie @kosamari. na Twitterze.