Narzędzie Chrome DevTools obsługuje teraz elementy najwyższej warstwy, co ułatwia deweloperom debugowanie kodu korzystającego z elementów najwyższej warstwy.
Z tego artykułu dowiesz się, czym są elementy najwyższej warstwy, jak DevTools pomagają wizualizować zawartość najwyższej warstwy, aby zrozumieć i debugować strukturę DOM zawierającą elementy najwyższej warstwy, oraz jak jest implementowana obsługa najwyższej warstwy w DevTools.
Czym jest najwyższa warstwa i jej elementy?
Co dokładnie dzieje się w systemie, gdy otworzysz <dialog>
jako okno modalne? 🤔
Jest on umieszczany w górnej warstwie. Treści z poziomu najwyższego renderują się nad wszystkimi innymi treściami. Na przykład modalny dialog musi być widoczny na wierzchu wszystkich innych elementów DOM, więc przeglądarka automatycznie renderuje ten element w „górnej warstwie”, zamiast zmuszać autorów do ręcznego stosowania indeksu z. Element górnej warstwy jest wyświetlany nad elementem, nawet jeśli ma najwyższą wartość wskaźnika z-index.
Warstwa najwyższa to „warstwa o najwyższym ułożeniu”. Każdy dokument ma powiązany jeden widok, a co za tym idzie, też jedną najwyższą warstwę. W najwyższej warstwie może znajdować się jednocześnie kilka elementów. W takim przypadku nakładają się na siebie, a ostatnia jest na wierzchu. Inaczej mówiąc, wszystkie elementy najwyższej warstwy są umieszczane w składce ostatni na wejściu, pierwszy na wyjściu (LIFO) w najwyższej warstwie.
Element <dialog>
nie jest jedynym elementem, który przeglądarka renderuje w najwyższej warstwie. Obecnie do warstwy górnej należą: wyskakiwania, okna modalne i elementy w trybie pełnoekranowym.
Zapoznaj się z implementacją tego dialogu:
<main>
<button onclick="window.dialog.showModal();">Open Dialog</button>
</main>
<dialog id="dialog"></dialog>
Oto demonstracja kilku dialogów z zastosowaniem stylów do tła (tła opisane poniżej):
Co to jest tło?
Na szczęście istnieje sposób na dostosowanie treści pod elementem najwyższej warstwy.
Każdy element w górnej warstwie ma pseudoelement CSS o nazwie tło.
Tło jest polem o rozmiarze równym widocznemu obszarowi, które jest renderowane bezpośrednio pod każdym elementem najwyższej warstwy. Pseudoelement ::backdrop
umożliwia zaciemnienie, stylizowanie lub całkowite ukrycie wszystkiego, co znajduje się pod elementem, gdy jest on najwyższy na najwyższej warstwie.
Gdy utworzysz wiele elementów modalnych, przeglądarka wyświetla tło bezpośrednio pod najbardziej wysuniętym elementem i nad innymi elementami pełnoekranowymi.
Aby nadać styl tła:
/* The browser displays the backdrop only when the dialog.showModal() function opens the dialog.*/
dialog::backdrop {
background: rgba(255,0,0,.25);
}
Jak wyświetlić tylko pierwszy tło?
Każdy element górnej warstwy ma tło należące do grupy warstw górnej. Te tła są zaprojektowane tak, aby nakładały się na siebie, więc jeśli krycie tła nie jest ustawione na 100%, widoczne są tła znajdujące się pod spodem.
Jeśli widoczne ma być tylko pierwsze tło w grupie warstw na górze, możesz to osiągnąć, śledząc identyfikatory elementów w grupie warstw na górze.
Jeśli dodany element nie jest pierwszym w najwyższej warstwie, funkcja wywoływana podczas umieszczania elementu w najwyższej warstwie stosuje klasę hiddenBackdrop
do ::backdrop
. Ta klasa jest usuwana, gdy element zostanie usunięty z górnej warstwy.
Zapoznaj się z kodem w tym przykładzie demonstracyjnym:
Projektowanie warstwy najwyższej w Narzędziach deweloperskich
Obsługa warstwy najwyższej w DevTools pomaga deweloperom zrozumieć koncepcję tej warstwy i zobaczyć, jak zmieniają się jej treści. Te funkcje pomagają deweloperom wykrywać:
- Elementy znajdujące się w górnej warstwie w dowolnym momencie i ich kolejność.
- Element znajdujący się na wierzchołku stosu w dowolnym momencie.
Ponadto obsługa warstwy najwyższej w DevTools pomaga wizualizować położenie pseudoelementu tła w grupie warstwy najwyższej. Chociaż nie jest elementem drzewa, odgrywa ważną rolę w działaniu najwyższej warstwy i może być przydatna deweloperom.
Dzięki funkcjom obsługi najwyższego poziomu możesz:
- W dowolnym momencie możesz sprawdzić, które elementy znajdują się na najwyższym poziomie. Reprezentacja najwyższej warstwy zmienia się dynamicznie w miarę dodawania i usuwania elementów z tej warstwy.
- sprawdzić położenie elementu w grupie warstw na wierzchu;
- Przejdź od elementu najwyższej warstwy lub elementu tła pseudoelementu elementów w drzewie do elementu lub elementu tła pseudoelementu w kontenerze reprezentacji najwyższej warstwy i z powrotem.
Zobaczmy, jak korzystać z tych funkcji.
Kontenery najwyższego poziomu
Aby ułatwić wizualizację elementów najwyższej warstwy, DevTools dodaje do drzewa elementów kontener najwyższej warstwy. Znajduje się on po tagu zamykającym </html>
.
Ten kontener pozwala w dowolnym momencie obserwować elementy w grupie warstwy górnej. Kontenery warstwy górnej to lista linków do elementów warstwy górnej i ich tła. Reprezentacja najwyższej warstwy zmienia się dynamicznie w miarę dodawania i usuwania elementów z tej warstwy.
Aby znaleźć elementy najwyższego poziomu w drzewie elementów lub kontenerze najwyższego poziomu, kliknij linki od reprezentacji elementu najwyższego poziomu w kontenerze najwyższego poziomu do tego samego elementu w drzewie elementów i z powrotem.
Aby przejść z elementu kontenera najwyższego poziomu do elementu drzewa najwyższego poziomu, kliknij przycisk pokaż obok elementu w kontenerze najwyższego poziomu.
Aby przejść z elementu drzewa najwyższej warstwy do linku w kontenerze najwyższej warstwy, kliknij plakietkę najwyższej warstwy obok elementu.
Możesz wyłączyć dowolną plakietkę, w tym plakietkę najwyższego poziomu. Aby wyłączyć plakietki, kliknij dowolną z nich prawym przyciskiem myszy, wybierz Ustawienia plakietki i usuń zaznaczenie przy plakietkach, które chcesz ukryć.
kolejność elementów w grupie warstwy najwyższej;
Kontenery warstwy górnej wyświetlają elementy w takim samym porządku, w jakim występują w grupie, ale w odwrotnej kolejności. Element na wierzchołku grupy jest ostatni na liście elementów kontenera najwyższej warstwy. Oznacza to, że ostatni element na liście kontenera najwyższej warstwy to element, z którym możesz obecnie wchodzić w interakcję w dokumencie.
Plakietki obok elementów drzewa wskazują, czy elementy należą do górnej warstwy, i zawierają numer pozycji elementu w steku.
Na tym zrzucie ekranu najwyższa warstwa składa się z 2 elementów, z których drugi znajduje się na górze. Jeśli usuniesz drugi element, pierwszy zostanie przesunięty na górę.
Tła w kontenerze najwyższej warstwy
Jak wspomnieliśmy powyżej, każdy element najwyższej warstwy ma pseudoelement CSS o nazwie tło. Możesz nadać temu elementowi styl, więc warto go też sprawdzić i zobaczyć jego reprezentację.
W drzewie elementów element tła znajduje się przed tagiem zamykającym element, do którego należy. W kontenerze najwyższej warstwy link do tła znajduje się jednak bezpośrednio nad elementem najwyższej warstwy, do którego należy.
Zmiany w drzewie DOM
ElementsTreeElement
, klasa odpowiedzialna za tworzenie i zarządzanie poszczególnymi elementami drzewa DOM w Narzędziach deweloperskich, nie wystarczała do zaimplementowania kontenera najwyższego poziomu.
Aby wyświetlić kontener najwyższego poziomu jako węzeł na drzewie, dodaliśmy nową klasę, która tworzy węzły elementów drzewa w DevTools. Wcześniej klasa odpowiedzialna za tworzenie drzewa elementów DevTools inicjowała każdą TreeElement
za pomocą DOMNode
, która jest klasą z backendNodeId
i innymi właściwościami powiązanymi z backendem. Zadanie backendNodeId
jest przypisane w backendzie.
Węzeł kontenera najwyższego poziomu, który zawiera listę linków do elementów najwyższego poziomu, potrzebny do działania jako zwykły węzeł elementu drzewa. Ten węzeł nie jest jednak „prawdziwym” węzłem DOM, a serwer nie musi tworzyć węzła kontenera najwyższego poziomu.
Aby utworzyć węzeł interfejsu użytkownika reprezentujący najwyższą warstwę, dodaliśmy nowy typ węzła interfejsu użytkownika, który jest tworzony bez DOMNode
. Ten element kontenera najwyższego poziomu jest pierwszym węzłem frontendu, który nie ma atrybutu DOMNode
, co oznacza, że istnieje tylko na froncie, a backend o nim „nie wie”. Aby zapewnić takie samo działanie jak w przypadku innych węzłów, utworzyliśmy nową klasę TopLayerContainer
, która rozszerza klasę UI.TreeOutline.TreeElement
odpowiedzialną za działanie węzłów frontendu.
Aby uzyskać pożądane umieszczenie, klasa renderująca element dołącza element TopLayerContainer
jako następny element nadrzędny elementu <html>
.
Nowa plakietka najwyższej warstwy wskazuje, że element znajduje się w najwyższej warstwie i służy jako link do skrótu tego elementu w elemencie TopLayerContainer
.
Początkowy projekt
Początkowo planowaliśmy powielanie elementów najwyższej warstwy w kontenerze najwyższej warstwy zamiast tworzenia listy linków do tych elementów. Nie wdrożyliśmy tego rozwiązania ze względu na sposób pobierania elementów podrzędnych w narzędziach deweloperskich. Każdy element ma wskaźnik nadrzędny używany do pobierania elementów podrzędnych, a nie można mieć wielu wskaźników. Dlatego nie możemy mieć węzła, który prawidłowo rozwija się i zawiera wszystkie węzły podrzędne w różnych miejscach w drzewie. Ogólnie system nie został zbudowany z myślą o powtarzających się poddrzewach.
Ustępstwem było utworzenie linków do węzłów DOM interfejsu zamiast ich duplikowania. Klasa odpowiedzialna za tworzenie linków do elementów w Narzędziach deweloperskich to ShortcutTreeElement
, która rozszerza klasę UI.TreeOutline.TreeElement
. ShortcutTreeElement
działa tak samo jak inne elementy drzewa DOM w DevTools, ale nie ma odpowiadającego mu węzła po stronie serwera i ma przycisk, który prowadzi do ElementsTreeElement
.
Każdy węzeł ShortcutTreeElement
w najwyższym poziomie ma element podrzędny ShortcutTreeElement
, który łączy się z reprezentacją pseudoelementu ::backdrop
w drzewie DOM w DevTools.
Początkowy projekt:
Zmiany w protokole Chrome DevTools (CDP)
Aby wdrożyć obsługę najwyższego poziomu, konieczne są zmiany w protokole CDP (Chrome DevTools Protocol). CDP służy jako protokół komunikacji między DevTools a Chromium.
Musimy dodać:
- Polecenie do wywołania w dowolnym momencie z poziomu interfejsu.
- Zdarzenie, które ma być wywoływane na froncie z poziomu backendu.
CDP: polecenie DOM.getTopLayerElements
Aby wyświetlić elementy bieżącej najwyższej warstwy, potrzebujemy nowego eksperymentalnego polecenia CDP, które zwraca listę identyfikatorów węzłów elementów znajdujących się w najwyższej warstwie. Narzędzia deweloperskie wywołują to polecenie, gdy są otwarte lub gdy zmieniają się elementy najwyższej warstwy. Polecenie wygląda tak:
# Returns NodeIds of the current top layer elements.
# Top layer renders closest to the user within a viewport, therefore, its elements always
# appear on top of all other content.
experimental command getTopLayerElements
returns
# NodeIds of the top layer elements.
array of NodeId nodeIds
CDP: zdarzenie DOM.topLayerElementsUpdated
Aby uzyskać aktualną listę elementów najwyższej warstwy, musimy wywołać zdarzenie eksperymentalnej CDP za każdym razem, gdy nastąpi zmiana elementów tej warstwy. To zdarzenie informuje interfejs o zmianie, która wywołuje polecenie DOM.getTopLayerElements
i otrzymuje listę nowych elementów.
Zdarzenie wygląda tak:
# Called by the change of the top layer elements.
experimental event topLayerElementsUpdated
Uwagi dotyczące CDP
Wdrożenie obsługi CDP na najwyższym poziomie było możliwe na kilka sposobów. Inną rozważaną przez nas opcją było utworzenie zdarzenia, które zwracałoby listę elementów najwyższej warstwy, zamiast tylko informować front-end o dodaniu lub usunięciu elementu z takiej warstwy.
Zamiast polecenia możemy też utworzyć 2 zdarzenia: topLayerElementAdded
i topLayerElementRemoved
. W tym przypadku otrzymamy element i będziemy musieli zarządzać tablicą elementów najwyższej warstwy na froncie.
Obecnie zdarzenie po stronie klienta wywołuje polecenie getTopLayerElements
, aby uzyskać listę zaktualizowanych elementów. Jeśli za każdym razem, gdy zostanie wywołane zdarzenie, wysyłalibyśmy listę elementów lub konkretny element, który spowodował zmianę, moglibyśmy pominąć jeden krok wywołania polecenia.
W tym przypadku interfejs nie miałby jednak kontroli nad tym, które elementy są przesyłane.
Zastosowaliśmy to rozwiązanie, ponieważ naszym zdaniem lepiej, gdy front-end decyduje, kiedy żądać węzłów najwyższego poziomu. Jeśli na przykład najwyższa warstwa jest zwinięta w interfejsie użytkownika lub użytkownik korzysta z panelu DevTools, który nie zawiera drzewa elementów, nie trzeba pobierać dodatkowych węzłów, które mogą znajdować się głębiej w drzewie.