ResizeObserver - ein neues leistungsstarkes Tool zum Arbeiten mit Anpassungsfähigkeit

Guten Tag, Freunde!

Responsive ist einer der Standards der Webentwicklung. Es gibt eine große Anzahl von Bildschirmauflösungen, und diese Anzahl nimmt ständig zu. Wir bemühen uns, alle möglichen Bildschirmgrößen unter Beibehaltung einer benutzerfreundlichen Oberfläche zu unterstützen. Eine hervorragende Lösung für dieses Problem sind Medienabfragen (Medienabfragen). Aber was ist mit Webkomponenten? Die moderne Webentwicklung basiert auf Komponenten, und wir brauchen eine Möglichkeit, sie reaktionsfähig zu machen. Heute möchte ich über die ResizeObserver-API sprechen, mit der Sie Änderungen der Größe eines bestimmten Elements und nicht des gesamten Ansichtsfensters überwachen (beobachten) können, wie dies bei Medienabfragen der Fall ist.

Ein bisschen Geschichte


Bisher standen uns nur Medienabfragen zur Verfügung - eine CSS-Lösung, die auf der Größe, dem Typ und der Auflösung des Bildschirms eines Mediengeräts basiert (mit einem Mediengerät meine ich einen Computer, ein Telefon oder ein Tablet). Medienabfragen sind sehr flexibel und einfach zu bedienen. Medienabfragen waren lange Zeit nur in CSS verfügbar, jetzt sind sie auch in JS über window.matchMedia (mediaQueryString) verfügbar. Jetzt können wir überprüfen, von welchem ​​Gerät die Seite angezeigt wird, und auch die Änderung der Größe des Anzeigebereichs überwachen (es handelt sich um die Methode MediaQueryList.addListener () - ca.

Elementabfragen


Was uns fehlte, war die Möglichkeit, die Größe eines einzelnen DOM-Elements und nicht nur des gesamten Ansichtsfensters zu überwachen. Entwickler beschweren sich seit vielen Jahren darüber. Dies ist eine der am meisten erwarteten Funktionen. Im Jahr 2015 wurde sogar ein Vorschlag unterbreitet - Anfragen nach Containergrößen ( Container Queries ):
Entwickler benötigen häufig die Möglichkeit, Elemente zu formatieren, wenn sie die Größe ihres übergeordneten Containers ändern, unabhängig vom Anzeigebereich. Anfragen nach Behältergrößen geben ihnen diese Möglichkeit. CSS-Verwendungsbeispiel:
.element: Medienbildschirm (min-width: 30em) {***}
Es klingt großartig, aber Browser-Anbieter hatten einen guten Grund, diesen Vorschlag abzulehnen - zirkuläre Abhängigkeit (zirkuläre Abhängigkeit) (wenn eine Größe eine andere definiert, führt dies zu einer Endlosschleife (mehr dazu finden Sie hier ). Welche anderen Möglichkeiten gibt es? Wir können window.resize (Rückruf) verwenden, aber dies ist ein "teures Vergnügen" - ein Rückruf wird jedes Mal aufgerufen, wenn ein Ereignis eintritt, und wir werden viele Berechnungen benötigen, um festzustellen, dass sich die Größe unserer Komponente wirklich geändert hat ...

Größe des Überwachungselements mithilfe der ResizeObserver-API ändern


Lernen Sie die ResizeObserver-API von Chrome kennen:
Die ResizeObserver-API ist eine Schnittstelle zum Verfolgen der Größenänderung von Elementen. Dies ist eine Art Analogon zum window.resize-Ereignis für ein Element.

Die ResizeObserver-API ist ein Live-Entwurf. Es ist bereits in Chrome, Firefox und Safari für PC implementiert. Die mobile Unterstützung ist weniger beeindruckend - nur Chrome für Android und Samsung Internet. Ein vollwertiges Polyphil gibt es leider nicht. Verfügbare Polyphile enthalten einige Einschränkungen (z. B. eine langsame Reaktion auf Größenänderungen oder mangelnde Unterstützung für einen reibungslosen Übergang). Dies sollte uns jedoch nicht davon abhalten, diese API zu testen. Also machen wir's!

Beispiel: Ändern des Texts beim Ändern der Größe eines Elements


Stellen Sie sich die folgende Situation vor: Der Text im Element sollte sich je nach Größe des Elements ändern. Die ResizeObserver-API bietet zwei Tools: ResizeObserver und ResizeObserverEntry. ResizeObserver wird verwendet, um die Größe eines Elements zu verfolgen, und ResizeObserverEntry enthält Informationen zu dem Element, dessen Größe geändert wurde.
Der Code ist sehr einfach:

<h1> size </h1>
<h2> boring text </h2>

const ro = new ResizeObserver(entries => {
    for(let entry of entries){
        const width = entry.contentBoxSize
        ? entry.contentBoxSize.inlineSize
        : entry.contentRect.width

        if(entry.target.tagName === 'H1'){
            entry.target.textContent = width < 1000 'small' : 'big'
        }

        if(entry.target.tagName === 'H2' && width < 500){
            entry.target.textContent = `I won't change anymore`
            ro.unobserve(entry.target) //  ,     500px
        }
    }
})

//       
ro.observe(document.querySelector('h1'))
ro.observe(document.querySelector('h2'))

Erstellen Sie zunächst ein ResizeObserver-Objekt und übergeben Sie ihm eine Rückruffunktion als Parameter:

const resizeObserver = new ResizeObserver((entries, observer) => {
    for(let entry of entries){
        // 
    }
})

Die Funktion wird jedes Mal aufgerufen, wenn die Größe eines der in ResizeObserverEntries enthaltenen Elemente geändert wird. Der zweite Parameter der Rückruffunktion ist der Beobachter selbst. Wir können es zum Beispiel verwenden, um die Verfolgung zu beenden, wenn eine bestimmte Bedingung erfüllt ist.

Callback erhält ein Array von ResizeObserverEntry. Jeder Eintrag enthält die Abmessungen des beobachteten Elements (Ziels).

for(let entry of entries){
    const width = entry.contentBoxSize
    ? entry.contentBoxSize.inlineSize
    : entry.contentRect.width

    if(entry.target.tagName === 'H1'){
        entry.target.textContent = width < 1000 ? 'small' : 'big'
    }
    ...
}

Wir haben drei Eigenschaften, die die Größe eines Elements beschreiben - borderBoxSize, contentBoxSize und contentRect. Sie stellen das Boxmodell des Elements dar, über das wir später sprechen werden. Nun ein paar Worte zur Unterstützung. Die meisten Browser unterstützen contentRect. Diese Eigenschaft wird jedoch anscheinend nicht mehr unterstützt:
contentRect erschien in der vorläufigen Entwicklungsphase von ResizeObserver und wurde nur im Interesse der aktuellen Kompatibilität hinzugefügt. Wahrscheinlich wird es in Zukunft als veraltet angesehen.


Daher würde ich die Verwendung von contentRect in Verbindung mit bordeBoxSize und contentBoxSize wärmstens empfehlen. ResizeObserverSize enthält zwei Eigenschaften: inlineSize und blockSize, die als Breite und Höhe interpretiert werden können (vorausgesetzt, wir arbeiten in der horizontalen Ausrichtung des Textes - Schreibmodus: horizontal).

Elementbeobachtung


Als letztes müssen Sie mit der Verfolgung des Artikels beginnen. Dazu rufen wir ResizeObserver.observe () auf. Diese Methode fügt der Liste der beobachteten Elemente ein neues Ziel hinzu. Wir können dieser Liste entweder ein oder mehrere Elemente gleichzeitig hinzufügen:

// resizeObserver(target, options)
ro.observe(document.querySelector('h1'))
ro.observe(document.querySelector('h2'))

Der zweite Parameter ist "optional". Bisher ist nur die Box verfügbar, die ein Blockmodell definiert. Mögliche Werte sind Content-Box (Standard), Border-Box und Device-Pixel-Content-Box (nur Chrome). In einem ResizeObserver kann nur ein Blockmodell definiert werden.

Verwenden Sie ResizeObserver.unobserve (Ziel), um die Überwachung zu beenden. Verwenden Sie ResizeObserver.disconnect (), um die Verfolgung aller Elemente zu beenden.

Blockmodell


Das Inhaltsfeld ist der Inhalt des Blocks ohne Auffüllung, Rand und Rand. Randfeld enthält Polsterung und Rand (kein Rand).



Das Inhaltsfeld für Gerätepixel ist der Inhalt des Elements in physischen Pixeln. Ich habe keine Beispiele für die Verwendung dieses Modells gesehen, aber es scheint, dass dies bei der Arbeit mit Leinwand nützlich sein kann. Hier ist eine interessante Diskussion zu diesem Thema auf Github.

Wann erfährt ein Beobachter von Veränderungen?


Jedes Mal, wenn die Größe des Zielelements geändert wird, wird ein Rückruf aufgerufen. Folgendes sagt die Spezifikation dazu:

  • Die Beobachtung wird ausgelöst, wenn ein beobachteter Gegenstand zum DOM hinzugefügt / daraus entfernt wird.
  • Die Beobachtung wird ausgelöst, wenn die Anzeigeeigenschaft des beobachteten Elements auf none gesetzt ist.
  • Die Beobachtung funktioniert nicht für "unsubstituierte" Linienelemente.
  • Beobachtung funktioniert bei der CSS-Transformation nicht.
  • , , .. , 0,0.

Gemäß dem ersten Absatz können wir die Änderung im übergeordneten Container bestimmen, wenn wir seine untergeordneten Container ändern. Ein gutes Beispiel für eine solche Verwendung der ResizeObserver-API ist das Scrollen im Chat-Fenster, wenn Sie eine neue Nachricht hinzufügen. Ein Beispiel ist zu sehen, hier .

Erinnern Sie sich an die Containergrößenabfragen, die ich zuvor erwähnt habe? Über sein Problem der zirkulären Abhängigkeit? Die ResizeObserver-API verfügt daher über eine integrierte Lösung, um eine Endlosschleife der "Größenänderung" zu verhindern. Lesen Sie hier darüber .

Vielen Dank für Ihre Aufmerksamkeit.

Nützliche Links: MDN CanIUse-

Spezifikation Erster Artikel des Entwicklungsteams Beliebteste Polyfil



Source: https://habr.com/ru/post/undefined/


All Articles