[ Web Proxy ]
URL:
Viewing: https://developer.mozilla.org/de/docs/Web/API/CustomStateSet [Back]  [Original]

CustomStateSet - Web-APIs | MDN

Dieser Inhalt wurde automatisch aus dem Englischen bersetzt, und kann Fehler enthalten. Erfahre mehr ber dieses Experiment.

View in English Always switch to English

CustomStateSet

Baseline 2024
Neu verfgbar

Seit Mai 2024 funktioniert diese Funktion auf aktuellen Gerten und in aktuellen Browserversionen. Auf lteren Gerten oder in lteren Browsern funktioniert sie mglicherweise nicht.

Die CustomStateSet-Schnittstelle des Document Object Model speichert eine Liste von Zustnden fr ein autonomes benutzerdefiniertes Element und erlaubt es, Zustnde zum Satz hinzuzufgen oder daraus zu entfernen.

Die Schnittstelle kann verwendet werden, um die internen Zustnde eines benutzerdefinierten Elements offenzulegen, sodass sie in CSS-Selektoren von Code, der das Element verwendet, genutzt werden knnen.

In diesem Artikel

Instanz-Eigenschaften

CustomStateSet.size

Gibt die Anzahl der Werte im CustomStateSet zurck.

Instanz-Methoden

CustomStateSet.add()

Fgt einen Wert zum Satz hinzu.

CustomStateSet.clear()

Entfernt alle Elemente aus dem CustomStateSet-Objekt.

CustomStateSet.delete()

Entfernt einen Wert aus dem CustomStateSet-Objekt.

CustomStateSet.entries()

Gibt einen neuen Iterator mit den Werten fr jedes Element im CustomStateSet in der Reihenfolge der Einfgung zurck.

CustomStateSet.forEach()

Fhrt eine bereitgestellte Funktion fr jeden Wert im CustomStateSet-Objekt aus.

CustomStateSet.has()

Gibt einen Boolean zurck, der angibt, ob ein Element mit dem angegebenen Wert vorhanden ist.

CustomStateSet.keys()

Ein Alias fr CustomStateSet.values().

CustomStateSet.values()

Gibt ein neues Iterator-Objekt zurck, das die Werte fr jedes Element im CustomStateSet-Objekt in der Reihenfolge der Einfgung liefert.

Beschreibung

In HTML eingebettete Elemente knnen verschiedene Zustnde haben, wie "aktiviert" und "deaktiviert", "ausgewhlt" und "nicht ausgewhlt", "initial", "ldt" und "bereit". Einige dieser Zustnde sind ffentlich und knnen ber Eigenschaften/Attribute gesetzt oder abgefragt werden, whrend andere effektiv intern sind und nicht direkt gesetzt werden knnen. Egal ob extern oder intern, Elementzustnde knnen im Allgemeinen mit CSS-Pseudoklassen als Selektoren ausgewhlt und gestylt werden.

Das CustomStateSet ermglicht es Entwickler*innen, Zustnde fr autonome benutzerdefinierte Elemente hinzuzufgen und zu lschen (nicht fr von eingebauten Elementen abgeleitete Elemente). Diese Zustnde knnen dann als benutzerdefinierte Zustands-Pseudoklassenselektoren auf hnliche Weise wie die Pseudoklassen fr eingebaute Elemente verwendet werden.

Benutzerdefinierte Zustnde von Elementen setzen

Um das CustomStateSet verfgbar zu machen, muss ein benutzerdefiniertes Element zunchst HTMLElement.attachInternals() aufrufen, um ein ElementInternals-Objekt anzuhngen. Das CustomStateSet wird dann von ElementInternals.states zurckgegeben. Beachten Sie, dass ElementInternals nicht an ein benutzerdefiniertes Element angehngt werden kann, das auf einem eingebauten Element basiert, sodass diese Funktion nur fr autonome benutzerdefinierte Elemente funktioniert (siehe github.com/whatwg/html/issues/5166).

Die CustomStateSet-Instanz ist ein Set-hnliches Objekt, das eine geordnete Menge von Zustandswerten enthalten kann. Jeder Wert ist ein benutzerdefinierter Identifikator. Identifikatoren knnen zur Menge hinzugefgt oder gelscht werden. Wenn ein Identifikator in der Menge vorhanden ist, ist der jeweilige Zustand true, whrend er entfernt wird, wenn der Zustand false ist.

Benutzerdefinierte Elemente, die Zustnde mit mehr als zwei Werten haben, knnen diese mit mehreren booleschen Zustnden darstellen, von denen nur einer gleichzeitig true (in der CustomStateSet vorhanden) ist.

Die Zustnde knnen innerhalb des benutzerdefinierten Elements verwendet werden, sind jedoch auerhalb der benutzerdefinierten Komponente nicht direkt zugnglich.

Interaktion mit CSS

Sie knnen ein benutzerdefiniertes Element auswhlen, das sich in einem bestimmten Zustand befindet, indem Sie die :state() benutzerdefinierte Zustands-Pseudoklasse verwenden. Das Format dieser Pseudoklasse ist :state(mein-zustandsname), wobei mein-zustandsname der Zustand ist, wie im Element definiert. Die benutzerdefinierte Zustands-Pseudoklasse stimmt mit dem benutzerdefinierten Element nur berein, wenn der Zustand true ist (d.h. wenn mein-zustandsname im CustomStateSet enthalten ist).

Zum Beispiel stimmt das folgende CSS mit einem benutzerdefinierten labeled-checkbox-Element berein, wenn das CustomStateSet des Elements den checked-Zustand enthlt, und wendet einen solid-Rand auf das Kontrollkstchen an:

css
labeled-checkbox:state(checked) {
  border: solid;
}

CSS kann auch verwendet werden, um einen benutzerdefinierten Zustand innerhalb eines benutzerdefinierten Elements im Shadow DOM zu verwenden, indem :state() innerhalb der :host()-Pseudoklassenfunktion angegeben wird.

Auerdem kann die :state()-Pseudoklasse nach dem ::part()-Pseudo-Element verwendet werden, um die Schatten-Teile (shadow parts) eines benutzerdefinierten Elements zu erfassen, die sich in einem bestimmten Zustand befinden.

Warnung: Browser, die :state() noch nicht untersttzen, verwenden ein CSS-<dashed-ident>, um benutzerdefinierte Zustnde auszuwhlen, das inzwischen veraltet ist. Informationen darber, wie Sie beide Anstze untersttzen knnen, finden Sie im Abschnitt Kompatibilitt mit <dashed-ident>-Syntax.

Beispiele

Den benutzerdefinierten Zustand eines benutzerdefinierten Kontrollkstchenelements anpassen

Dieses Beispiel, das aus der Spezifikation adaptiert wurde, zeigt ein benutzerdefiniertes Kontrollkstchenelement, das einen internen "checked"-Zustand hat. Dieser wird dem benutzerdefinierten checked-Zustand zugeordnet, wodurch Styling durch die :state(checked)-Pseudo-Klasse angewendet werden kann.

JavaScript

Zuerst definieren wir unsere Klasse LabeledCheckbox, die von HTMLElement abgeleitet ist. Im Konstruktor rufen wir die super()-Methode auf, fgen einen Listener fr das Klick-Ereignis hinzu und rufen this.attachInternals() auf, um ein ElementInternals-Objekt anzuhngen.

Der Groteil der verbleibenden "Arbeit" wird dann connectedCallback() berlassen, das aufgerufen wird, wenn ein benutzerdefiniertes Element zur Seite hinzugefgt wird. Der Inhalt des Elements wird mit Hilfe eines <style>-Elements definiert, das entweder den Text [] oder [x] gefolgt von einem Label anzeigt. Bemerkenswert ist hier, dass die benutzerdefinierte Zustands-Pseudoklasse verwendet wird, um den anzuzeigenden Text auszuwhlen: :host(:state(checked)). Nach dem folgenden Beispiel werden wir im Detail darauf eingehen, was im Schnipsel geschieht.

js
class LabeledCheckbox extends HTMLElement {
  constructor() {
    super();
    this._boundOnClick = this._onClick.bind(this);
    this.addEventListener("click", this._boundOnClick);

    // Attach an ElementInternals to get states property
    this._internals = this.attachInternals();
  }

  connectedCallback() {
    const shadowRoot = this.attachShadow({ mode: "open" });
    shadowRoot.innerHTML = `<style>
  :host {
    display: block;
  }
  :host::before {
    content: "[ ]";
    white-space: pre;
    font-family: monospace;
  }
  :host(:state(checked))::before {
    content: "[x]";
  }
</style>
<slot>Label</slot>
`;
  }

  get checked() {
    return this._internals.states.has("checked");
  }

  set checked(flag) {
    if (flag) {
      this._internals.states.add("checked");
    } else {
      this._internals.states.delete("checked");
    }
  }

  _onClick(event) {
    // Toggle the 'checked' property when the element is clicked
    this.checked = !this.checked;
  }

  static isStateSyntaxSupported() {
    return CSS.supports("selector(:state(checked))");
  }
}

customElements.define("labeled-checkbox", LabeledCheckbox);

// Display a warning to unsupported browsers
if (!LabeledCheckbox.isStateSyntaxSupported()) {
  if (!document.getElementById("state-warning")) {
    const warning = document.createElement("div");
    warning.id = "state-warning";
    warning.style.color = "red";
    warning.textContent = "This feature is not supported by your browser.";
    document.body.insertBefore(warning, document.body.firstChild);
  }
}

In der LabeledCheckbox-Klasse:

  • In den get checked() und set checked()-Methoden verwenden wir ElementInternals.states, um das CustomStateSet zu erhalten.
  • Die set checked(flag)-Methode fgt den "checked"-Identifikator dem CustomStateSet hinzu, wenn das Flag gesetzt ist, und entfernt den Identifikator, wenn das Flag false ist.
  • Die get checked()-Methode prft nur, ob die checked-Eigenschaft im Satz definiert ist.
  • Der Eigenschaftswert wird umgeschaltet, wenn auf das Element geklickt wird.

Wir rufen dann die define()-Methode auf dem Objekt auf, das von Window.customElements zurckgegeben wird, um das benutzerdefinierte Element zu registrieren:

js
customElements.define("labeled-checkbox", LabeledCheckbox);

HTML

Nach der Registrierung des benutzerdefinierten Elements knnen wir das Element in HTML wie folgt verwenden:

html
<labeled-checkbox>You need to check this</labeled-checkbox>

CSS

Schlielich verwenden wir die :state(checked)-Pseudo-Klasse, um CSS fr den Zustand des Kontrollkstchens auszuwhlen, wenn es ausgewhlt ist.

css
labeled-checkbox {
  border: dashed red;
}
labeled-checkbox:state(checked) {
  border: solid;
}

Ergebnis

Klicken Sie auf das Element, um zu sehen, dass ein anderer Rahmen angewendet wird, whrend der checked-Zustand des Kontrollkstchens umgeschaltet wird.

Einen benutzerdefinierten Zustand in einem Schatten-Teil eines benutzerdefinierten Elements anpassen

Dieses Beispiel, das aus der Spezifikation adaptiert wurde, zeigt, dass benutzerdefinierte Zustnde verwendet werden knnen, um die Schatten-Teile (shadow parts) eines benutzerdefinierten Elements fr das Styling zu erfassen. Schatten-Teile sind Abschnitte des Shadow DOMs, die absichtlich fr Seiten freigegeben werden, die das benutzerdefinierte Element verwenden.

Das Beispiel erstellt ein <question-box>-benutzerdefiniertes Element, das eine Frageaufforderung zusammen mit einem Kontrollkstchen mit der Bezeichnung "Ja" anzeigt. Fr das Kontrollkstchen wird das im vorherigen Beispiel definierte <labeled-checkbox> verwendet.

JavaScript

Zuerst definieren wir die benutzerdefinierte QuestionBox-Elementklasse, die von HTMLElement abgeleitet ist. Wie immer ruft der Konstruktor zunchst die super()-Methode auf. Als Nchstes fgen wir der benutzerdefinierten Komponente durch Aufruf von attachShadow() einen Schatten-DOM-Baum hinzu.

js
class QuestionBox extends HTMLElement {
  constructor() {
    super();
    const shadowRoot = this.attachShadow({ mode: "open" });
    shadowRoot.innerHTML = `<div><slot>Question</slot></div>
<labeled-checkbox part="checkbox">Yes</labeled-checkbox>
`;
  }
}

Der Inhalt der Schattenwurzel wird mit innerHTML festgelegt. Dies definiert ein <slot>-Element, das den Standardaufforderungstext "Question" fr das Element enthlt. Dann definieren wir ein benutzerdefiniertes <labeled-checkbox>-Element mit dem Standardtext "Ja". Dieses Kontrollkstchen wird als Schatten-Teil der Fragebox mit dem Namen checkbox ber das part-Attribut freigegeben.

Beachten Sie, dass der Code und das Styling fr das <labeled-checkbox>-Element genau das gleiche wie im vorherigen Beispiel sind und daher hier nicht wiederholt werden.

Dann rufen wir die define()-Methode auf dem Objekt auf, das von Window.customElements zurckgegeben wird, um das benutzerdefinierte Element mit dem Namen question-box zu registrieren:

js
customElements.define("question-box", QuestionBox);

HTML

Nach der Registrierung des benutzerdefinierten Elements knnen wir das Element in HTML wie folgt verwenden:

html
<!-- Question box with default prompt "Question" -->
<question-box></question-box>

<!-- Question box with custom prompt "Continue?" -->
<question-box>Continue?</question-box>

CSS

Der erste CSS-Block erfasst den freigegebenen Schatten-Teil namens checkbox mithilfe des ::part()-Selectors und stylt ihn standardmig red.

css
question-box::part(checkbox) {
  color: red;
}

Der zweite Block folgt ::part() mit :state(), um checkbox-Teile zu erfassen, die sich im checked-Zustand befinden:

css
question-box::part(checkbox):state(checked) {
  color: green;
  outline: dashed 1px green;
}

Ergebnis

Klicken Sie auf eines der Kontrollkstchen, um den Farbwechsel von rot zu grn mit einer Umrandung zu beobachten, whrend der checked-Zustand umgeschaltet wird.

Nicht-boolesche interne Zustnde

Dieses Beispiel zeigt, wie man mit dem Fall umgeht, in dem das benutzerdefinierte Element eine interne Eigenschaft mit mehreren mglichen Werten hat.

Das benutzerdefinierte Element in diesem Fall hat eine state-Eigenschaft mit erlaubten Werten: "loading", "interactive" und "complete". Um dies zu ermglichen, ordnen wir jeden Wert seinem benutzerdefinierten Zustand zu und erstellen Code, um sicherzustellen, dass nur der Identifikator, der dem internen Zustand entspricht, gesetzt ist. Sie knnen dies in der Implementierung der set state()-Methode sehen: Wir setzen den internen Zustand, fgen den Identifikator fr den passenden benutzerdefinierten Zustand zum CustomStateSet hinzu und entfernen die Identifikatoren, die mit allen anderen Werten verknpft sind.

Der Groteil des restlichen Codes hnelt dem Beispiel, das einen einzelnen booleschen Zustand zeigt (wir zeigen fr jeden Zustand unterschiedlichen Text, whrend der Benutzer sie durchluft).

JavaScript

js
class ManyStateElement extends HTMLElement {
  constructor() {
    super();
    this._boundOnClick = this._onClick.bind(this);
    this.addEventListener("click", this._boundOnClick);
    // Attach an ElementInternals to get states property
    this._internals = this.attachInternals();
  }

  connectedCallback() {
    this.state = "loading";

    const shadowRoot = this.attachShadow({ mode: "open" });
    shadowRoot.innerHTML = `<style>
  :host {
    display: block;
    font-family: monospace;
  }
  :host::before {
    content: "[ unknown ]";
    white-space: pre;
  }
  :host(:state(loading))::before {
    content: "[ loading ]";
  }
  :host(:state(interactive))::before {
    content: "[ interactive ]";
  }
  :host(:state(complete))::before {
    content: "[ complete ]";
  }
</style>
<slot>Click me</slot>
`;
  }

  get state() {
    return this._state;
  }

  set state(stateName) {
    // Set internal state to passed value
    // Add identifier matching state and delete others
    if (stateName === "loading") {
      this._state = "loading";
      this._internals.states.add("loading");
      this._internals.states.delete("interactive");
      this._internals.states.delete("complete");
    } else if (stateName === "interactive") {
      this._state = "interactive";
      this._internals.states.delete("loading");
      this._internals.states.add("interactive");
      this._internals.states.delete("complete");
    } else if (stateName === "complete") {
      this._state = "complete";
      this._internals.states.delete("loading");
      this._internals.states.delete("interactive");
      this._internals.states.add("complete");
    }
  }

  _onClick(event) {
    // Cycle the state when element clicked
    if (this.state === "loading") {
      this.state = "interactive";
    } else if (this.state === "interactive") {
      this.state = "complete";
    } else if (this.state === "complete") {
      this.state = "loading";
    }
  }

  static isStateSyntaxSupported() {
    return CSS.supports("selector(:state(loading))");
  }
}

customElements.define("many-state-element", ManyStateElement);

if (!LabeledCheckbox.isStateSyntaxSupported()) {
  if (!document.getElementById("state-warning")) {
    const warning = document.createElement("div");
    warning.id = "state-warning";
    warning.style.color = "red";
    warning.textContent = "This feature is not supported by your browser.";
    document.body.insertBefore(warning, document.body.firstChild);
  }
}

HTML

Nach der Registrierung des neuen Elements fgen wir es dem HTML hinzu. Dies hnelt dem Beispiel, das einen einzelnen booleschen Zustand zeigt, jedoch geben wir keinen Wert an und verwenden den Standardwert aus dem Slot (<slot>Click me</slot>).

html
<many-state-element></many-state-element>

CSS

Im CSS verwenden wir die drei benutzerdefinierten Zustands-Pseudoklassen, um CSS fr jeden der internen Zustandswerte auszuwhlen: :state(loading), :state(interactive), :state(complete). Beachten Sie, dass der benutzerdefinierte Elementcode sicherstellt, dass nur einer dieser benutzerdefinierten Zustnde gleichzeitig definiert werden kann.

css
many-state-element:state(loading) {
  border: dotted grey;
}
many-state-element:state(interactive) {
  border: dashed blue;
}
many-state-element:state(complete) {
  border: solid green;
}

Ergebnisse

Klicken Sie auf das Element, um zu sehen, dass bei der nderung des Zustands ein anderer Rahmen angewendet wird.

Kompatibilitt mit <dashed-ident>-Syntax

Frher wurden benutzerdefinierte Elemente mit benutzerdefinierten Zustnden mit einem <dashed-ident> anstelle der :state()-Funktion ausgewhlt. Browser-Versionen, die :state() nicht untersttzen, werfen einen Fehler, wenn ein Identifikator verwendet wird, der nicht mit dem doppelten Strich (double dash) prfixiert ist. Wenn Untersttzung fr diese Browser erforderlich ist, verwenden Sie entweder einen try...catch Block, um beide Syntaxen zu untersttzen, oder verwenden Sie ein <dashed-ident> als Zustandswert und whlen Sie ihn sowohl mit dem :--my-state als auch mit dem :state(--my-state) CSS-Selektor aus.

Verwendung eines try...catch Blocks

Der nachstehende Code zeigt, wie Sie try...catch verwenden knnen, um zu versuchen, einen Zustands-Identifikator hinzuzufgen, der kein <dashed-ident> verwendet, und auf <dashed-ident> zurckzugreifen, wenn ein Fehler auftritt.

JavaScript

js
class CompatibleStateElement extends HTMLElement {
  constructor() {
    super();
    this._internals = this.attachInternals();
  }

  connectedCallback() {
    // The double dash is required in browsers with the
    // legacy syntax, not supplying it will throw
    try {
      this._internals.states.add("loaded");
    } catch {
      this._internals.states.add("--loaded");
    }
  }
}

CSS

css
compatible-state-element:is(:--loaded, :state(loaded)) {
  border: solid green;
}

Verwendung der mit Doppelstrich verupakan Identifikatoren

Eine alternative Lsung kann die Verwendung des <dashed-ident> innerhalb von JavaScript sein. Der Nachteil bei diesem Ansatz ist, dass die Striche bei der Verwendung der CSS-:state()-Syntax eingeschlossen werden mssen.

JavaScript

js
class CompatibleStateElement extends HTMLElement {
  constructor() {
    super();
    this._internals = this.attachInternals();
  }
  connectedCallback() {
    // The double dash is required in browsers with the
    // legacy syntax, but works with the modern syntax
    this._internals.states.add("--loaded");
  }
}

CSS

css
compatible-state-element:is(:--loaded, :state(--loaded)) {
  border: solid green;
}

Spezifikationen

Spezifikation
HTML
# customstateset

Browser-Kompatibilitt

Siehe auch

Verwendung benutzerdefinierter Elemente


Web Proxy Viewer  |  New URL  |  Original Page