Startseite / Artikel

Fragment-Referenzen in React 19.3: DOM-Behavior für Geschwistergruppen, ohne Wrapper

Erfahren Sie, wie Ihnen ein Ref in Fragment eine FragmentInstance für Zuhörer, Fokus, Beobachter sowie Messungen über aufeinanderfolgende Elemente bereitstellt und wo seine Grenzen liegen.

Verlag: REACTAPP.TOP12 Min. Lesezeit2858 Wörter

Quellen: React 19.3 Fragment Refs: Listen, Focus, Observe and Measure a Group of Elements Without a Wrapper div

Die meisten React-Codebasen enthalten ein <div>, das nur dazu dient, dass etwas einen ref enthalten kann. Vielleicht hat das Komponente, das Sie messen wollten, mehrere Geschwisterkomponenten gerendert, oder es stammt aus einer Bibliothek, die ihren ref niemals weitergeleitet hat. Das zusätzliche Element stört dann eine Grid- oder Flex-Anordnung, beeinträchtigt die :nth-child-Styling-Regeln oder erzeugt bei <tr>-Elementen ungültiges HTML. React 19.3 stuft Fragment-Refs als stabil ein: Wenn Sie einen ref an <Fragment> hängen, erhalten Sie eine FragmentInstance, die gängige DOM-Operationen wie Zuhören, Fokussieren, Beobachten, Messen und Scrollen gleichzeitig auf alle Kinder des Fragments anwendet, ohne etwas zum gerenderten Baum hinzuzufügen. Dieser Artikel behandelt die API, praktische Muster für jede Funktion, welche Kinder jede Methode betrifft sowie die Fallstricke, die man vor der Veröffentlichung kennen sollte.

Weil diese Funktion zum Zeitpunkt der Erstellung neu ist, prüfen Sie die aktuelle <Fragment>-Referenz auf Änderungen in den Methodennamen oder im Verhalten.

Die FragmentInstance-API

In einer typischen Konfiguration wird Fragment explizit importiert, da die Referenz erst nach dem Einbinden vorhanden ist:

import { Fragment, useRef, useEffect } from 'react';

Die Referenz beginnt mit null und wird zu einer FragmentInstance, sobald das Fragment eingebunden ist. Der folgende Code schützt vor null, fügt einen Zuhörer hinzu und entfernt ihn bei der Bereinigung:

function Group({ children }) {
  const ref = useRef(null);            // becomes a FragmentInstance after mount
  useEffect(() => {
    const instance = ref.current;
    if (instance === null) return;
    instance.addEventListener('click', onClick);
    return () => instance.removeEventListener('click', onClick);
  }, []);
  return <Fragment ref={ref}>{children}</Fragment>;
}

Das explizite <Fragment>-Element ist erforderlich. Die Abkürzung <>…</> akzeptiert weder eine ref noch eine key. Hier ist, was die Instanz bereitstellt:

  • addEventListener(type, fn, opts?) und removeEventListener: Sie wirken auf die Kinder des ersten DOM-Niveaus und werden auf nachträglich hinzugefügte oder entfernte Kinder übertragen.
  • dispatchEvent(event): Sendet das Ereignis direkt am Fragment selbst ab; mit bubbles: true wird das Ereignis an den übergeordneten DOM-Node weitergeleitet.
  • focus(opts?) und focusLast(opts?): Suchen tiefgehend in allen verschachtelten Nachkommen nach dem ersten oder letzten fokussierbaren Element und akzeptieren { preventScroll }.
  • blur(): Macht das aktive Element unscharf, sofern es sich innerhalb des Fragments befindet, ansonsten geschieht nichts.
  • observeUsing(observer) und unobserveUsing(observer): Registrieren von Kindern erster Ebene des DOM mit einem IntersectionObserver oder ResizeObserver; Textknoten sind nicht enthalten.
  • getClientRects(): Gibt eine flache Liste DOMRect[] für die Kinder erster Ebene des DOM zurück.
  • scrollIntoView(alignToTop?): Scrollt bei true das erste Kind in Sichtweite und bei false das letzte Kind; es wird nur ein Boolescher Wert akzeptiert, ein Options-Objekt führt zu einem Fehler.
  • getRootNode() und compareDocumentPosition(node): Beschreiben die Position des Fragments nach denselben Konventionen wie die Node-Methoden.
  • Ein Listener für eine Gruppe von Kindern

    Ein häufiges Szenario ist eine Werkzeugleiste, die von einer von Ihnen nicht kontrollierten Komponente dargestellt wird, bei der Sie einen einzigen Klick-Listener für alle ihre Schaltflächen möchten – beispielsweise zur Übermittlung von Analysedaten. Die Demo importiert:

    import { Fragment, useRef, useEffect, useState } from 'react';
    

    Toolbar steht für eine Komponente von Drittanbietern: Sie zeigt einfache Schwesterschaltflächen ohne Wrapper und ohne ref an, sowie optional eine vierte Schaltfläche. Tracked umhüllt seine Kinder in einen mit ref versehenen Fragment und fügt im Zuge eines Effects den onAny-Handler hinzu, der bei Änderungen des Handlers erneut angehängt wird. App protokolliert den Text jeder geklickten Schaltfläche und bietet ein Kontrollkästchen an, um die zusätzliche Schaltfläche hinzuzufügen:

    // Imagine this comes from a library: no ref, no wrapper, just siblings.
    function Toolbar({ extra }) {
      return (
        <>
          <button>Bold</button>
          <button>Italic</button>
          <button>Link</button>
          {extra && <button>Emoji</button>}
        </>
      );
    }function Tracked({ children, onAny }) {
      const ref = useRef(null);
      useEffect(() => {
        const instance = ref.current;
        if (instance === null) return;
        instance.addEventListener('click', onAny);
        return () => instance.removeEventListener('click', onAny);
      }, [onAny]);
      return <Fragment ref={ref}>{children}</Fragment>;
    }export default function App() {
      const [log, setLog] = useState([]);
      const [extra, setExtra] = useState(false);
      return (
        <>
          <div className="bar">
            <Tracked onAny={e => setLog(l => [e.target.textContent, ...l].slice(0, 6))}>
              <Toolbar extra={extra} />
            </Tracked>
          </div>
          <label><input type="checkbox" checked={extra} onChange={e => setExtra(e.target.checked)} /> add a fourth button</label>
          <p className="log">clicked: {log.join(' · ') || '—'}</p>
        </>
      );
    }
    

    Die Styles legen lediglich die Anordnung der Werkzeugleiste sowie der Protokolllinie fest:

    .bar { display: flex; gap: 8px; margin-bottom: 10px; }
    .log { margin: 10px 0 0; font-family: ui-monospace, monospace; opacity: .8; }
    

    Aktivieren Sie die vierte Schaltfläche und klicken Sie darauf – sie wird genauso protokolliert wie die anderen. Die Fragmentinstanz verfolgt die Kinderkomponenten, während React sie montiert und demontiert, und aktualisiert entsprechend ihre Zuhörerfunktionen, was genau die Buchhaltung ist, die man sonst selbst durchführen müsste. Beachten Sie, dass onAny in der Demo eine inline-Arrow-Funktion ist, wodurch der Effekt bei jeder Renderung von App erneut angemeldet wird; in echtem Code sollte man ihn mit useCallback stabilisieren, falls diese Häufigkeit von Bedeutung ist.

    Fokussierung durch verschachtelte Inhalte

    Nur focus() und focusLast() schauen über die erste Ebene hinaus. Sie durchlaufen alle Nachkommen in tiefen-ersten Reihenfolge, bis sie ein fokussierbares Element finden – daher ist auch ein Eingabefeld, das innerhalb eines Labels innerhalb eines Fieldsets liegt, noch erreichbar. Dadurch wird „den ersten Feld in diesem Abschnitt fokussieren“ selbst für Markup, das man nicht selbst erstellt hat, trivial.

    Die Demo importiert nur Fragment und useRef:

    import { Fragment, useRef } from 'react';
    

    Section rendernt einen Titel sowie drei Schaltflächen, die mit focus(), focusLast() und blur() auf der Fragment-Instanz verknüpft sind, und rendernt anschließend seine Kinder innerhalb des mit ref referenzierten Fragment. App übermittelt zwei Fieldsets mit beschrifteten Eingabefeldern:

    function Section({ title, children, controls }) {
      const ref = useRef(null);
      return (
        <>
          <div className="row">
            <strong>{title}</strong>
            <button onClick={() => ref.current.focus()}>First field</button>
            <button onClick={() => ref.current.focusLast()}>Last field</button>
            <button onClick={() => ref.current.blur()}>Blur</button>
          </div>
          <Fragment ref={ref}>{children}</Fragment>
        </>
      );
    }export default function App() {
      return (
        <Section title="Shipping">
          <fieldset>
            <legend>Address</legend>
            <label>Street <input name="street" /></label>{' '}
            <label>City <input name="city" /></label>
          </fieldset>
          <fieldset>
            <legend>Contact</legend>
            <label>Phone <input name="phone" /></label>
          </fieldset>
        </Section>
      );
    }
    

    Ein Fokusring macht das Ergebnis sichtbar:

    .row { display: flex; gap: 8px; align-items: center; margin-bottom: 10px; }
    fieldset { border-radius: 8px; margin: 0 0 8px; }
    input:focus { outline: 3px solid light-dark(#2563eb, #60a5fa); }
    

    „Erstes Feld“ landet bei Street, obwohl es sich innerhalb eines <label> in einem <fieldset> befindet, und „Letztes Feld“ bei Phone. Diese tiefenfirstige Suche unterscheidet sich von Events und Observern, die bereits auf der ersten Ebene stoppen; der Abschnitt zu Zielsetzung unten erklärt den Grund.

    Sichtbarkeit überwachen, ohne die Layouts zu stören

    observeUsing() nimmt einen von Ihnen selbst erstellten Observer entgegen, sodass Sie die Kontrolle über root, threshold und rootMargin behalten, und die Instanz registriert jedes Kind erster Ebene bei sich. Im nächsten Beispiel werden die neuesten Chatnachrichten als gelesen markiert, sobald eine von ihnen innerhalb des scrollbaren Gesprächsfensters sichtbar wird. Ein Wrapper-Element um diese Nachrichten hätte die Flex-Anordnung des Fensters gestört, bei der sich jede Nachrichtsfensterblase unabhängig ausrichtet.

    Zu den Importen gehört useLayoutEffect, damit der Observer vor dem Zeichnen registriert wird:

    import { Fragment, useRef, useLayoutEffect, useState } from 'react';
    

    ReadReceipt erstellt einen IntersectionObserver, der am Scrollbereich mit einem Schwellenwert von 0,6 angesetzt wird, ruft onRead auf, sobald ein Eintrag mit diesem Bereich kollidiert, und räumt den Observer schließlich mit unobserveUsing auf. App zeigt vierzehn Nachrichten an und umschließt die letzten drei mit ReadReceipt:

    function ReadReceipt({ root, onRead, children }) {
      const ref = useRef(null);
      useLayoutEffect(() => {
        const instance = ref.current;
        const io = new IntersectionObserver(
          entries => { if (entries.some(e => e.isIntersecting)) onRead(); },
          { root: root.current, threshold: 0.6 }
        );
        instance.observeUsing(io);
        return () => instance.unobserveUsing(io);
      }, [root, onRead]);
      return <Fragment ref={ref}>{children}</Fragment>;
    }const MESSAGES = Array.from({ length: 14 }, (_, i) => `Message ${i + 1}`);export default function App() {
      const pane = useRef(null);
      const [read, setRead] = useState(false);
      return (
        <>
          <p className="status">{read ? '✅ Priya has read your last messages' : 'scroll the pane to the bottom…'}</p>
          <div className="pane" ref={pane}>
            {MESSAGES.slice(0, 11).map(m => <div key={m} className="bubble">{m}</div>)}
            <ReadReceipt root={pane} onRead={() => setRead(true)}>
              {MESSAGES.slice(11).map(m => <div key={m} className="bubble mine">{m}</div>)}
            </ReadReceipt>
          </div>
        </>
      );
    }
    

    Durch das CSS wird der Scrollbereich zu einer scrollbaren Flex-Säule, wobei die eigenen Nachrichten des Benutzers rechts ausgerichtet werden:

    .status { margin: 0 0 8px; font-weight: 600; }
    .pane { height: 190px; overflow: auto; display: flex; flex-direction: column; gap: 6px; padding: 8px; border-radius: 10px; background: light-dark(#f1f5f9, #262a33); }
    .bubble { align-self: flex-start; padding: 6px 10px; border-radius: 12px; background: light-dark(#fff, #363b47); }
    .mine { align-self: flex-end; background: light-dark(#dbeafe, #1e3a5f); }
    

    ResizeObserver funktioniert genauso. Wenn Sie viele Gruppen verwalten, die dieselben Observer-Einstellungen teilen, benötigen Sie keinen Observer pro Gruppe: Jedes Kind erster Ebene besitzt eine reactFragments-Eigenschaft, die einen Set der zu ihm gehörenden Fragment-Instanzen enthält, wodurch ein einziger Observer für jeden Eintrag die zugehörige Gruppe ermitteln und den richtigen Handler aufrufen kann.

    Messung einer Gruppe von Geschwistern

    getClientRects() gibt für jedes Kind erster Ebene ein Rechteck zurück. Durch Kombinieren dieser Rechtecke erhält man den Umrandungskasten der gesamten Gruppe, den man nutzen kann, um eine Auswahlhervorhebung oder Klammern um mehrere ungültige Felder zu zeichnen, ohne die Anordnung der darin befindlichen Kinder zu verändern.

    Die Demo importiert:

    import { Fragment, useRef, useState, useLayoutEffect } from 'react';
    

    Outline liest die Rechtecke bei Aktivierung eines Layout-Effekts, berechnet das minimale Oben- und Links- sowie das maximale Unten- und Rechts-Maß, fügt Scroll-Offsete sowie etwas Abstand hinzu und speichert das Ergebnis. Anschließend wird ein absolut positionierter Umrandungskasten neben dem Fragment dargestellt. App platziert zwei Gruppen à drei Eingabefelder im selben Raster und ermöglicht es dem Benutzer, auszuwählen, welche Gruppe umrandet werden soll:

    function Outline({ active, children }) {
      const ref = useRef(null);
      const [box, setBox] = useState(null);
      useLayoutEffect(() => {
        if (!active) return setBox(null);
        const rects = ref.current.getClientRects();
        const top = Math.min(...rects.map(r => r.top)), left = Math.min(...rects.map(r => r.left));
        const bottom = Math.max(...rects.map(r => r.bottom)), right = Math.max(...rects.map(r => r.right));
        setBox({ top: top + scrollY - 6, left: left + scrollX - 6, width: right - left + 12, height: bottom - top + 12 });
      }, [active]);
      return (
        <>
          <Fragment ref={ref}>{children}</Fragment>
          {box && <div className="outline" style={box} />}
        </>
      );
    }export default function App() {
      const [which, setWhich] = useState('none');
      return (
        <>
          <div className="row">
            {['none', 'address', 'card'].map(w => (
              <label key={w}><input type="radio" checked={which === w} onChange={() => setWhich(w)} /> {w}</label>
            ))}
          </div>
          <div className="grid">
            <Outline active={which === 'address'}>
              <input placeholder="Street" /><input placeholder="City" /><input placeholder="PIN" />
            </Outline>
            <Outline active={which === 'card'}>
              <input placeholder="Card number" /><input placeholder="MM/YY" /><input placeholder="CVV" />
            </Outline>
          </div>
        </>
      );
    }
    

    Das Raster hat drei Spalten, und der Rahmen ist mit pointer-events: none absolut positioniert, sodass er niemals Klicks abfängt:

    .row { display: flex; gap: 14px; margin-bottom: 10px; }
    .grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
    .grid input { min-width: 0; }
    .outline { position: absolute; pointer-events: none; border: 2px dashed light-dark(#dc2626, #f87171); border-radius: 8px; }
    

    Jeder Eingabefeld hier ist ein unmittelbares Kind desselben CSS-Rasters. Wenn man jede Gruppe in einen <div> einbettet, würden die drei Eingabefelder in eine Zelle gepresst; mit einem Fragment bleibt das Raster unberührt und jede Gruppe kann weiterhin gemessen werden. Eine Einschränkung der Demo besteht darin, dass der Box-Status nur dann neu berechnet wird, wenn sich active ändert, wodurch ein Fensterumbau oder eine sich bewegende Scroll-Container dazu führen können, dass der Status veraltet bleibt. Dies lässt sich durch die Kombination mit einem ResizeObserver über observeUsing beheben.

    Welche Kinder jede Methode anspricht

    Die meisten Methoden arbeiten mit dem, was React als Erststuflieger-Kindelemente bezeichnet – also den DOM-Elementen, die man durch das Durchlaufen von React-Komponenten erreicht, bis man auf ein echtes Element stößt. In diesen eingebetteten Elementen wird nicht direkt zugegriffen.

    <Fragment ref={ref}>
      <div id="A" />
      <Wrapper>              {/* a component, not a DOM node: looked through */}
        <div id="B">
          <div id="C" />     {/* inside a DOM node: NOT targeted */}
        </div>
      </Wrapper>
      <div id="D" />
    </Fragment>
    // addEventListener / observeUsing / getClientRects → A, B, D
    // focus / focusLast → search A, B, C, D depth-first
    

    In diesem Baum ist Wrapper eine Komponente, weshalb React sie durchsucht und B als Erststuflieger-Element gilt. C befindet sich innerhalb des DOM-Elements B, daher ist es kein direktes Ziel. Listener, Observer und rects beziehen sich somit auf A, B und D, während focus und focusLast in tiefforstgeschichtlicher Reihenfolge nach A, B, C und D suchen.

    Der Unterschied ist beabsichtigt. Da Ereignisse aufsteigen, erreichen Klicks innerhalb von C bereits einen Zuhörer in B, und der Box- sowie Beobachtungsbereich von B umfasst bereits C. Fokus hat kein entsprechendes Aufsteigeverhalten, und das Element, das den Fokus erhalten kann, befindet sich in jeder Tiefe – daher müssen diese beiden Methoden suchen.

    Die Workarounds, die dadurch ersetzt werden

    Vor Fragment Refs gab es drei gängige Ansätze, von denen jeder einen Nachteil hatte:

    • Ein Wrapper-Element, <div ref={ref}><Thing /></div>: Es fügt ein neues Flex- oder Grid-Element dort ein, wo zuvor eine Reihe von Geschwisterelementen war, bricht die Selektoren :first-child und :nth-child auf, fügt eine Layout-Box hinzu und ist zwischen Tabellenzeilen oder Listenelementen völlig ungültig.
  • Änderung des Components, um dessen Ref weiterzuleiten oder ein innerRef-Attribut zu akzeptieren: funktionsfähig für eigenen Code, unmöglich für ein Paket, und es erzeugt dennoch nur einen einzigen Knoten.
  • Absuchen im DOM über einen Elternelement-Ref, beispielsweise parent.querySelectorAll('button') innerhalb eines Effects: es funktioniert nicht mehr, sobald sich die Kinder nach Ausführung des Effects ändern, wodurch eine veraltete Liste an Listern übrig bleibt.
  • Warum das nützlich ist

    Mit Fragment Refs können Sie Verhalten um fremde Markup-Strukturen hinzufügen, ohne diese unverändert zu lassen. Dadurch entstehen natürlicherweise Komponentenfamilien, die ausschließlich aus Verhalten bestehen: <Tracked>, <InView>, <FocusScope>, <Outline>. Jede dieser Komponenten setzt sich aus einem Fragment und einem Effekt zusammen, funktioniert mit beliebigen Kindkomponenten und fügt dem DOM nichts hinzu. Entwickler von Design-Systemen profitieren am meisten davon: Eine Menu-Komponente kann den Fokus unter den von ihren Nutzern dargestellten Elementen steuern, ohne diesen Elementen eine bestimmte Struktur aufzuzwingen. Das React-Changelog beschreibt dies als komponierbares Plattformverhalten – ein gutes mentales Modell: Das Fragment ist der Ort, an dem das Verhalten liegt, während die Kindkomponenten beliebige Form annehmen können.

    Aufzupassende Fallstricke vor dem Einsatz

    • Ein Ref benötigt die vollständige Schreibweise; <> akzeptiert diese nicht.
  • Vor dem Mount enthält der Ref null, daher sollte jeder Effekt zunächst darauf prüfen.
  • Listener, Observer und Messungsmethoden schauen nur ein DOM-Niveau tief, während die beiden Fokusmethoden den gesamten Unterbaum durchlaufen.
  • scrollIntoView akzeptiert nur einen Boolean-Wert. Die Übermittlung von { behavior: 'smooth' } führt zu einem Fehler. Verwenden Sie scrollIntoView(), um das erste Kind an die Oberkante auszurichten, oder scrollIntoView(false), um das letzte Kind an die Unterkante auszurichten.
  • Fragmente, die nur Text enthalten, können nicht beobachtet werden, da observeUsing Elemente als Ziel hat; React warnt in der Entwicklungsversion davor.
  • In einem versteckten <Activity>-Baum werden Listener, die während der Versteckung hinzugefügt wurden, nur dann angehängt, wenn der Unterbaum sichtbar wird.
  • Version 19.3 behebte ein Leck bei Listenern (#36047): Die Erfassungsoptionen wurden nicht wie von der DOM-Spezifikation gefordert normalisiert, wodurch eine Registrierung mit { capture: true } und eine Deregistrierung mit einem einfachen true dazu führten, dass der Listener weiterhin aktiv blieb. Stellen Sie sicher, dass Sie eine stabile Version verwenden, bevor Sie auf Listenern in der Erfassungsphase vertrauen.
  • focus() setzt voraus, dass das Fenster den Fokus im Betriebssystem hat. React stellt sicher, dass ein Element den Fokus erhält, indem es auf sein focus-Event wartet, während Chrome dieses Event überspringt, wenn das Browserfenster nicht aktiv ist. Bei headless- oder im Hintergrund ausgeführten Tests wurde beobachtet, dass focusLast() an „Phone“ vorbeigeht und den Fokus bei „Street“ belässt; achten Sie daher darauf, dass die Testseite tatsächlich den Fokus hat, bevor Sie überprüfen, wo dieser gelandet ist.
  • Eine FragmentInstance ist kein Element, daher existieren Eigenschaften wie classList, style und innerHTML nicht bei ihr; alles, was sie benötigt, verlangt weiterhin nach einem echten DOM-Node.
  • Eine Alternative für React 19.2 und frühere Versionen

    Für den Fall mit dem Zuhörer ist die sinnvollste Alternative die Delegation von Ereignissen über einen Elternteil-Ref. Da der Handler beim Elternteil liegt und e.target.closest('button') überprüft, können Kinderelemente hinzugefügt oder entfernt werden, ohne dass eine erneute Verknüpfung erforderlich ist:

    function Tracked({ children, onAny }) {
      const parent = useRef(null);
      useEffect(() => {
        const el = parent.current;
        const handler = (e) => { if (e.target.closest('button')) onAny(e); };
        el.addEventListener('click', handler);
        return () => el.removeEventListener('click', handler);
      }, [onAny]);
      return <div ref={parent} style={{ display: 'contents' }}>{children}</div>;
    }
    

    Der Stil display: contents entfernt das eigene Box-Modell des Wrapper-Elements, sodass flex- und grid-basierte Eltern die Kinder als direkte Elemente behandeln. Es handelt sich dennoch um ein Element: Es darf nicht innerhalb eines <table> stehen, Bildschirmleser und ähnliche Tools haben es manchmal falsch interpretiert, und zur Messung oder Beobachtung der Kinder ist weiterhin querySelectorAll erforderlich. Es eignet sich für Listener und Fokussierung, doch bei Beobachtungs- und Messfunktionen ist tatsächlich Version 19.3 notwendig.

    Haupterkenntnisse

    • Ein ref auf einem expliziten <Fragment> liefert eine FragmentInstance, die Listening, Fokussierung, Beobachtung, Messung und Scrollen über Geschwisterelemente ohne zusätzlichen DOM-Node bündelt.
    • Listener und Beobachter bleiben synchron, wenn Kinder hinzugefügt oder entfernt werden, wodurch manuelles Verwalten entfällt.
  • Die meisten Methoden richten sich auf Kinder des ersten Levels; nur focus und focusLast durchsuchen den gesamten Unterbaum, da focus nicht nach oben weitergeleitet wird.
  • Achten Sie auf die wichtigen Aspekte: scrollIntoView funktioniert nur mit Booleschen Werten, es gibt keine Beobachtung ausschließlich von Text, in Tests wird der Fokus auf dem Fenster gesetzt sowie die Capture-Listener-Lösung in Version 19.3 eingeführt.
  • Verpackungen, die sich ausschließlich auf das Verhalten beziehen – wie Tracking-, Sichtbarkeits- und Fokusscopes – werden zu einfachen, wiederverwendbaren Komponenten.
  • Für die vollständige Liste der Methoden sowie Einschränkungen siehe die offizielle Fragment-Dokumentation; die entsprechenden Pull Requests finden sich im Projekt-Changelog.