Unterstützung der obersten Ebene in den Chrome-Entwicklertools

Alina Varkki
Alina Varkki

In den Chrome-Entwicklertools werden Elemente der obersten Ebene unterstützt, was es Entwicklern erleichtert, Fehler in ihrem Code zu beheben, in dem Elemente der obersten Ebene verwendet werden.

In diesem Artikel wird beschrieben, was Elemente der obersten Ebene sind, wie die Entwicklertools die Inhalte der obersten Ebene visualisieren, um die DOM-Struktur, die Elemente der obersten Ebene enthält, zu verstehen und zu debuggen, und wie die Unterstützung der obersten Ebene in den Entwicklertools implementiert wird.

Was sind die Elemente der obersten Ebene und der Ebene der obersten Ebene?

Was genau geschieht intern, wenn Sie ein <dialog> als modales Fenster öffnen? 🤔

Sie wird in eine oberste Ebene gelegt. Der Inhalt der obersten Ebene wird über allen anderen Inhalten gerendert. Beispielsweise muss ein modales Dialogfeld über allen anderen DOM-Inhalten angezeigt werden, sodass der Browser dieses Element automatisch auf einer „obersten Ebene“ rendert, anstatt Autoren dazu zu zwingen, den Z-Index manuell zu bekämpfen. Ein Element der obersten Ebene erscheint auch mit dem höchsten Z-Index über einem Element.

Die obere Ebene kann als „höchste Stapelebene“ bezeichnet werden. Jedes Dokument hat einen einzelnen Darstellungsbereich und daher auch eine einzelne oberste Ebene. Auf der obersten Ebene können sich mehrere Elemente gleichzeitig befinden. In diesem Fall werden sie übereinander gestapelt. Mit anderen Worten: Alle Elemente der obersten Ebene werden in einem LIFO-Stapel (Last In, First Out) in der obersten Ebene platziert.

Das <dialog>-Element ist nicht das einzige Element, das der Browser in einem obersten Layer rendert. Aktuell sind die Elemente der obersten Ebene Popovers, modale Dialogfelder und Elemente im Vollbildmodus.

Sehen Sie sich die folgende Implementierung des Dialogfelds an:

<main>
  <button onclick="window.dialog.showModal();">Open Dialog</button>
</main>
<dialog id="dialog"></dialog>

Hier sehen Sie eine Demo mit einigen Dialogfeldern, bei denen Stile auf die Hintergründe angewendet wurden (Bilderrahmen, die unten beschrieben werden):

Was ist ein Hintergrund?

Glücklicherweise gibt es auch eine Möglichkeit, den Inhalt unter dem obersten Layer-Element anzupassen.

Jedes Element auf der obersten Ebene hat ein CSS-Pseudoelement, das als Bilderrahmen bezeichnet wird.

Der Bilderrahmen ist ein Feld in der Größe des Darstellungsbereichs, das direkt unter dem obersten Ebenenelement gerendert wird. Mit dem Pseudoelement ::backdrop können Sie alles, was sich unterhalb des obersten Elements befindet, überdecken, gestalten oder vollständig ausblenden.

Wenn Sie mehrere Elemente als modales Element festlegen, zeichnet der Browser den Hintergrund direkt unter dem vordersten Element und über anderen Vollbildelementen.

So gestalten Sie einen Hintergrund:

/* The browser displays the backdrop only when the dialog.showModal() function opens the dialog.*/
dialog::backdrop {
    background: rgba(255,0,0,.25);
}

Wie wird nur der erste Bilderrahmen angezeigt?

Jedes Element der obersten Ebene hat einen Hintergrund, der zu einem übergeordneten Ebenenstapel gehört. Diese Hintergründe sind so konzipiert, dass sie sich überlappen. Wenn die Deckkraft eines Hintergrunds nicht zu 100 % beträgt, sind die Hintergründe sichtbar.

Wenn nur der erste Hintergrund im obersten Layer-Stapel sichtbar sein muss, können Sie dies erreichen, indem Sie die Element-IDs im obersten Layer-Stapel erfassen.

Wenn das hinzugefügte Element nicht das erste auf der obersten Ebene ist, wendet die Funktion, die beim Verschieben des Elements in die oberste Ebene aufgerufen wird, eine hiddenBackdrop-Klasse auf die ::backdrop an. Diese Klasse wird entfernt, wenn das Element vom obersten Layer entfernt wird.

Sehen Sie sich den Code in dieser Beispieldemo an:

Design der obersten Ebene mit Unterstützung in den Entwicklertools

Die Unterstützung der Entwicklertools der obersten Ebene hilft Entwicklern, das Konzept der obersten Ebene zu verstehen und zu visualisieren, wie sich die Inhalte auf der obersten Ebene ändern. Diese Funktionen helfen Entwicklern, Folgendes zu erkennen:

  • Die Elemente auf der obersten Ebene und ihre Reihenfolge
  • Das Element, das sich an einer beliebigen Stelle oben im Stapel befindet

Darüber hinaus hilft die Unterstützung der obersten Ebene in den Entwicklertools dabei, die Position des Pseudoelements für den Hintergrund im Stapel der obersten Ebene zu visualisieren. Obwohl es sich nicht um ein Baumelement handelt, spielt es eine wichtige Rolle bei der Funktionsweise der obersten Ebene und kann für Entwickler nützlich sein.

Mit den Funktionen der obersten Ebene können Sie:

  1. Sie können jederzeit sehen, welche Elemente sich im Stapel der obersten Ebene befinden. Der Darstellungsstapel der obersten Ebene ändert sich dynamisch, wenn Elemente zur obersten Ebene hinzugefügt oder von ihr entfernt werden.
  2. Sieh dir die Position des Elements im Stapel der obersten Ebene an.
  3. Springen Sie vom Pseudoelement des Hintergrundelements oder des Hintergrundelements der obersten Ebene in der Baumstruktur zum Pseudoelement oder Hintergrundelement im Darstellungscontainer der obersten Ebene und zurück.

Sehen wir uns an, wie diese Funktionen verwendet werden.

Container der obersten Ebene

Zur Visualisierung der Elemente der obersten Ebene fügen die Entwicklertools einen Container der obersten Ebene hinzu. Es befindet sich nach dem schließenden </html>-Tag.

Mit diesem Container können Sie die Elemente im obersten Layer-Stapel jederzeit betrachten. Der Container der obersten Ebene ist eine Liste von Links zu den Elementen der obersten Ebene und ihren Hintergründen. Der Darstellungsstapel der obersten Ebene ändert sich dynamisch, wenn Elemente zur obersten Ebene hinzugefügt oder von ihr entfernt werden.

Wenn Sie die Elemente der obersten Ebene innerhalb der Elementstruktur oder des Containers der obersten Ebene suchen möchten, klicken Sie auf die Links in der Darstellung der obersten Ebene im Container der obersten Ebene zu demselben Element in der Elementstruktur und zurück.

Wenn Sie vom Containerelement der obersten Ebene zum Baumelement der obersten Ebene wechseln möchten, klicken Sie neben dem Element im Container der obersten Ebene auf die Schaltfläche Anzeigen.

Springt vom Containerlink der obersten Ebene zum Element

Wenn Sie vom Baumelement der obersten Ebene zum Link im Container der obersten Ebene wechseln möchten, klicken Sie neben dem Element auf das Badge oberste Ebene.

Von einem Element zum Containerlink der obersten Ebene springen

Du kannst jedes Badge deaktivieren, auch das oberste Abzeichen. Um die Badges zu deaktivieren, klicken Sie mit der rechten Maustaste auf ein Abzeichen, wählen Sie Abzeicheneinstellungen aus und entfernen Sie die Häkchen neben den Badges, die Sie ausblenden möchten.

Das Badge wird deaktiviert.

Reihenfolge der Elemente im Stapel der obersten Ebene

Im Container der obersten Ebene werden die Elemente so angezeigt, wie sie im Stapel angezeigt werden, aber in umgekehrter Reihenfolge. Der obere Bereich des Stapelelements ist das letzte Element in der Elementliste des obersten Layer-Containers. Das bedeutet, dass das letzte Element in der Containerliste der obersten Ebene das Element ist, mit dem Sie derzeit im Dokument interagieren können.

Die Kennzeichen neben den Baumelementen geben an, ob die Elemente zur obersten Ebene gehören und die Positionsnummer eines Elements im Stapel enthalten.

In diesem Screenshot besteht der oberste Layer-Stapel aus zwei Elementen, wobei sich das zweite Element oben im Stapel befindet. Wenn Sie das zweite Element entfernen, wird das erste an den Anfang verschoben.

Die Reihenfolge der Elemente im Stapel.

Bilderrahmen im Container der obersten Ebene

Wie bereits erwähnt, verfügt jedes Element der obersten Ebene über ein CSS-Pseudoelement namens „Hintergrund“. Sie können dieses Element mit einem Stil versehen, daher ist es sinnvoll, es auch zu überprüfen und seine Darstellung zu sehen.

Im Elementbaum befindet sich ein Hintergrundelement vor dem schließenden Tag des Elements, zu dem es gehört. Im Container der obersten Ebene wird jedoch ein Hintergrundlink direkt über dem übergeordneten Ebenenelement aufgelistet, zu dem er gehört.

Stapelposition des Bilderrahmens.

Änderungen an der DOM-Baumstruktur

ElementsTreeElement, die Klasse, die für das Erstellen und Verwalten einzelner DOM-Baumelemente in den Entwicklertools verantwortlich ist, reichte nicht aus, um einen Container auf der obersten Ebene zu implementieren.

Damit der Container der obersten Ebene als Knoten in der Baumstruktur angezeigt wird, haben wir eine neue Klasse hinzugefügt, die Entwicklertools-Baumelementknoten erstellt. Bisher war die Klasse für das Erstellen der Entwicklertools-Elementstruktur verantwortlich, die alle TreeElement mit einer DOMNode initialisiert hat. Dabei handelt es sich um eine Klasse mit einer backendNodeId und anderen Backend-bezogenen Attributen. backendNodeId wiederum wird im Back-End zugewiesen.

Der Containerknoten der obersten Ebene, der eine Liste von Links zu Elementen der obersten Ebene enthält, der erforderlich ist, um sich wie ein normaler Baumelementknoten zu verhalten. Dieser Knoten ist jedoch kein "echter" DOM-Knoten und das Backend muss den Containerknoten der obersten Ebene nicht erstellen.

Um einen Frontend-Knoten zu erstellen, der die oberste Ebene darstellt, haben wir einen neuen Typ von Frontend-Knoten hinzugefügt, der ohne DOMNode erstellt wird. Dieses Containerelement der obersten Ebene ist der erste Frontend-Knoten ohne DOMNode. Das bedeutet, dass es nur im Frontend vorhanden ist und das Backend davon nicht "weiß". Um dasselbe Verhalten wie andere Knoten zu zeigen, haben wir eine neue TopLayerContainer-Klasse erstellt, die die UI.TreeOutline.TreeElement-Klasse erweitert, die für das Verhalten von Frontend-Knoten verantwortlich ist.

Um das gewünschte Placement zu erreichen, hängt die Klasse, die ein Element rendert, TopLayerContainer als nächstes gleichgeordnetes Element des <html>-Tags an.

Ein neues Badge für die oberste Ebene zeigt an, dass sich das Element auf der obersten Ebene befindet. Es dient als Link zur Verknüpfung dieses Elements im TopLayerContainer-Element.

Ursprüngliches Design

Zuerst bestand der Plan darin, Elemente der obersten Ebene in den Container der obersten Ebene zu duplizieren, anstatt eine Liste mit Links zu den Elementen zu erstellen. Wir haben diese Lösung nicht implementiert, weil das Abrufen der untergeordneten Elemente von Elementen in den Entwicklertools nicht funktioniert. Jedes Element verfügt über einen übergeordneten Zeiger, der zum Abrufen von untergeordneten Elementen verwendet wird, und es ist unmöglich, mehrere Zeiger zu haben. Daher gibt es keinen Knoten, der ordnungsgemäß erweitert wird und alle untergeordneten Elemente an mehreren Stellen in der Baumstruktur enthält. Bei der Erstellung des Systems wurden im Allgemeinen keine doppelten Unterstrukturen berücksichtigt.

Die Manipulation bestand darin, Links zu den Frontend-DOM-Knoten zu erstellen, anstatt diese Knoten zu duplizieren. Die Klasse, die für das Erstellen von Links zu Elementen in den Entwicklertools verantwortlich ist, ist ShortcutTreeElement. Damit wird UI.TreeOutline.TreeElement erweitert. ShortcutTreeElement verhält sich genauso wie andere DOM-Baumelemente in den Entwicklertools, hat aber keinen entsprechenden Knoten im Backend und eine Schaltfläche, die mit einer ElementsTreeElement verknüpft ist. Jeder ShortcutTreeElement zum Knoten der obersten Ebene hat ein untergeordnetes ShortcutTreeElement, das mit der Darstellung eines ::backdrop-Pseudoelements im DOM-Baum der Entwicklertools verknüpft ist.

Ursprüngliches Design:

Ursprüngliches Design

Änderungen beim Chrome DevTools Protocol (CDP)

Zur Implementierung der Unterstützung der obersten Ebene sind Änderungen am Chrome DevTools Protocol (CDP) erforderlich. CDP dient als Kommunikationsprotokoll zwischen den Entwicklertools und Chromium.

Wir müssen Folgendes hinzufügen:

  • Ein Befehl, der jederzeit vom Front-End aus aufgerufen werden kann.
  • Ein Ereignis, das im Frontend von der Backend-Seite aus ausgelöst werden soll.

CDP: DOM.getTopLayerElements-Befehl

Um die aktuellen Elemente der obersten Ebene anzuzeigen, benötigen wir einen neuen experimentellen CDP-Befehl, der eine Liste der Knoten-IDs der Elemente auf der obersten Ebene zurückgibt. Die Entwicklertools rufen diesen Befehl immer dann auf, wenn die Entwicklertools geöffnet werden oder wenn sich die Elemente der obersten Ebene ändern. Der Befehl sieht folgendermaßen aus:

  # 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: DOM.topLayerElementsUpdated Ereignis

Um eine aktuelle Liste der Elemente der obersten Ebene zu erhalten, muss jede Änderung an den Elementen der obersten Ebene ein experimentelles CDP-Ereignis auslösen. Dieses Ereignis informiert das Front-End über die Änderung, die dann den Befehl DOM.getTopLayerElements aufruft und die neue Elementliste empfängt.

Das Ereignis sieht so aus:

  # Called by the change of the top layer elements.
  experimental event topLayerElementsUpdated

CDP-Überlegungen

Es gab mehrere Möglichkeiten, die CDP-Unterstützung der obersten Ebene zu implementieren. Eine andere Option, die wir in Betracht gezogen haben, bestand darin, ein Ereignis zu erstellen, bei dem die Liste der Elemente der obersten Ebene zurückgegeben und nicht nur das Frontend über das Hinzufügen oder Entfernen eines Elements der obersten Ebene informiert wird.

Alternativ können Sie zwei Ereignisse anstelle des Befehls erstellen: topLayerElementAdded und topLayerElementRemoved. In diesem Fall empfangen wir ein -Element und müssten das Array der obersten Layer-Elemente am Frontend verwalten.

Derzeit ruft ein Frontend-Ereignis den Befehl getTopLayerElements auf, um eine Liste aktualisierter Elemente abzurufen. Wenn wir bei jedem Auslösen eines Ereignisses eine Liste von Elementen oder ein bestimmtes Element senden würden, das die Änderung verursacht hat, könnten wir einen Schritt des Befehlsaufrufs vermeiden. Allerdings würde das Front-End in diesem Fall nicht mehr steuern, welche Elemente übertragen werden.

Wir haben es auf diese Weise implementiert, da es unserer Meinung nach besser ist, wenn das Front-End entscheidet, wann Knoten der obersten Ebene angefordert werden. Wenn beispielsweise die oberste Ebene in der Benutzeroberfläche minimiert ist oder der Nutzer einen Entwicklertools-Bereich verwendet, der den Elementbaum nicht enthält, müssen keine zusätzlichen Knoten bereitgestellt werden, die sich weiter unten im Baum befinden könnten.