MDC-112 Web: Integration von MDC in Web-Frameworks

1. Einführung

logo_components_color_2x_web_96dp.png

Material Components (MDC) unterstützen Entwickler bei der Implementierung von Material Design. MDC wurde von einem Team aus Entwicklern und UX-Designern bei Google entwickelt. Es enthält Dutzende schöne und funktionale UI-Komponenten und ist für Android, iOS, das Web und Flutter.material.io/develop verfügbar.

MDC Web wurde für die Integration in jedes Frontend-Framework entwickelt, wobei die Prinzipien von Material Design aufrechterhalten werden. Im folgenden Codelab erfahren Sie, wie Sie eine React-Komponente erstellen, die MDC Web als Grundlage verwendet. Die in diesem Codelab erlernten Prinzipien lassen sich auf jedes JavaScript-Framework anwenden.

So funktioniert MDC Web

Die JavaScript-Ebene von MDC Web besteht aus drei Klassen pro Komponente: Component, Foundation und Adapter. Durch dieses Muster kann MDC Web flexibel in Frontend-Frameworks integrieren.

Die Foundation enthält die Geschäftslogik, die Material Design implementiert. Die Foundation verweist auf keine HTML-Elemente. Dadurch kann die HTML-Interaktionslogik im Adapter abstrahiert werden. Foundation hat einen Adapter.

Der Adapter ist eine Schnittstelle. Die Foundation verweist auf die Adapter-Schnittstelle, um die Geschäftslogik von Material Design zu implementieren. Sie können den Adapter in verschiedenen Frameworks wie Angular oder React implementieren. Eine Implementierung eines Adapters interagiert mit der DOM-Struktur.

Die Komponente hat eine Grundlage und hat die Aufgabe,

  1. Implementieren Sie den Adapter mithilfe von Nicht-Framework-JavaScript und
  2. Stellen Sie öffentliche Methoden bereit, die für Methoden in der Grundlagen stehen.

Was MDC Web bietet

Jedes Paket in MDC Web enthält eine Komponente, eine Grundlage und einen Adapter. Zum Instanziieren einer Component muss das Stammelement element an die Konstruktormethode der Komponente übergeben werden. Die Komponente implementiert einen Adapter, der mit dem DOM und den HTML-Elementen interagiert. Die Component instanziiert dann die Foundation, wodurch die Adapter-Methoden aufgerufen werden.

Um MDC Web in ein Framework zu integrieren, müssen Sie Ihre eigene Component in der Sprache und Syntax dieses Frameworks erstellen. Die Komponente des Frameworks implementiert den Adapter von MDC Web und verwendet die Foundation von MDC Web.

Inhalt

In diesem Codelab wird gezeigt, wie Sie einen benutzerdefinierten Adapter erstellen, um mithilfe der Foundation-Logik eine Material Design-React-Komponente zu erstellen. Er behandelt die weiterführenden Themen unter In Frameworks integrieren. React wird in diesem Codelab als Beispiel-Framework verwendet, kann aber auch auf jedes andere Framework angewendet werden.

In diesem Codelab erstellen Sie die obere App-Leiste und erstellen die obere Demoseite neu. Das Layout der Demoseite ist bereits eingerichtet, sodass Sie mit der Arbeit an der oberen App-Leiste beginnen können. Die obere App-Leiste umfasst Folgendes:

  • Navigationssymbol
  • Maßnahmen
  • Es gibt vier Varianten: kurze, immer minimiert, feste und gut sichtbare Varianten.

Sie benötigen:

  • Eine aktuelle Version von Node.js, die im JavaScript-Paketmanager npm enthalten ist
  • Der Beispielcode (wird im nächsten Schritt heruntergeladen)
  • Grundkenntnisse in HTML, CSS, JavaScript und React

Wie würden Sie Ihre Erfahrung mit Webentwicklung bewerten?

<ph type="x-smartling-placeholder"></ph> Neuling Mittel Kompetent

2. Entwicklungsumgebung einrichten

Starter-Codelab-App herunterladen

Die Start-App befindet sich im Verzeichnis material-components-web-codelabs-master/mdc-112/starter.

...oder von GitHub klonen

Führen Sie die folgenden Befehle aus, um dieses Codelab von GitHub zu klonen:

git clone https://github.com/material-components/material-components-web-codelabs
cd material-components-web-codelabs/mdc-112/starter

Projektabhängigkeiten installieren

Führen Sie im Startverzeichnis material-components-web-codelabs/mdc-112/starter folgenden Befehl aus:

npm install

Es werden viele Aktivitäten angezeigt. Am Ende sollte das Terminal eine erfolgreiche Installation anzeigen:

22a33efc2a687408.png

Starter-App ausführen

Führen Sie im selben Verzeichnis folgenden Befehl aus:

npm start

webpack-dev-server wird gestartet. Rufen Sie in Ihrem Browser http://localhost:8080/ auf, um die Seite aufzurufen.

b55c66dd400cf34f.png

Fertig! Der Startcode für die Demoseite der Top App Bar React sollte in deinem Browser ausgeführt werden. Sie sollten eine Wand mit lorem ipsum-Text, ein Feld Steuerelemente (unten rechts) und eine unfertige obere App-Leiste sehen:

4ca3cf6d216f9290.png

Code und Projekt ansehen

Wenn Sie Ihren Code-Editor öffnen, sollte das Projektverzeichnis in etwa so aussehen:

e9a3270d6a67c589.png

Öffnen Sie die Datei App.js und sehen Sie sich die Methode render an, die die Komponente <TopAppBar> enthält:

App.js

render() {
    const {isFixed, isShort, isRtl, isProminent, isAlwaysCollapsed, shouldReinit} = this.state;

    return (
      <section
        dir={isRtl ? 'rtl' : 'ltr'}
        className='mdc-typography'>
        {
          shouldReinit ? null :
          <TopAppBar
            navIcon={this.renderNavIcon()}
            short={isShort}
            prominent={isProminent}
            fixed={isFixed}
            alwaysCollapsed={isAlwaysCollapsed}
            title='Mountain View, CA'
            actionItems={this.actionItems}
          />
        }
        <div className={classnames('mdc-top-app-bar--fixed-adjust', {
          'mdc-top-app-bar--short-fixed-adjust': isShort || isAlwaysCollapsed,
          'mdc-top-app-bar--prominent-fixed-adjust': isProminent,
        })}>
          {this.renderDemoParagraphs()}
        </div>

        {this.renderControls()}
      </section>
    );
  }

Dies ist der Einstiegspunkt für TopAppBar in der Anwendung.

Öffnen Sie die Datei TopAppBar.js, eine reine React-Klasse Component, mit der Methode render:

TopAppBar.js

import React from 'react';

export default class TopAppBar extends React.Component {
  render() {
    return (
      <header>
        TOP APP BAR
      </header>
    );
  }
}

3. Zusammensetzung der Komponente

In React gibt die Methode render den HTML-Code der Komponente aus. Die Komponente der oberen App-Leiste rendert ein <header />-Tag und besteht aus zwei Hauptabschnitten:

  1. Navigationssymbol und Titelbereich
  2. Bereich für Aktionssymbole

Weitere Informationen zu den Elementen, aus denen die Top App Bar besteht, finden Sie in der GitHub.

Ändern Sie die Methode render() in TopAppBar.js so:

  render() {
    const {
      title,
      navIcon,
    } = this.props;

    return (
      <header
        className={this.classes}
        style={this.getMergedStyles()}
        ref={this.topAppBarElement}
      >
        <div className='mdc-top-app-bar__row'>
          <section className='mdc-top-app-bar__section mdc-top-app-bar__section--align-start'>
            {navIcon ? navIcon : null}
            <span className="mdc-top-app-bar__title">
              {title}
            </span>
          </section>
          {this.renderActionItems()}
        </div>
      </header>
    );
  }

Dieser HTML-Code enthält zwei Abschnittselemente. Das erste enthält ein Navigationssymbol und einen Titel. Das zweite enthält Aktionssymbole.

Fügen Sie als Nächstes die Methode renderActionItems hinzu:

renderActionItems() {
  const {actionItems} = this.props;
  if (!actionItems) {
    return;
  }

  return (
    <section className='mdc-top-app-bar__section mdc-top-app-bar__section--align-end' role='toolbar'>
      {/* need to clone element to set key */}
      {actionItems.map((item, key) => React.cloneElement(item, {key}))}
    </section>
  );
}

Ein Entwickler importiert TopAppBar in seine React-Anwendung und übergibt Aktionssymbole an das TopAppBar-Element. In App.js sehen Sie Beispielcode, mit dem ein TopAppBar initialisiert wird.

Die Methode getMergedStyles fehlt, die in der Methode render verwendet wird. Füge der TopAppBar-Klasse die folgende JavaScript-Methode hinzu:

getMergedStyles = () => {
  const {style} = this.props;
  const {style: internalStyle} = this.state;
  return Object.assign({}, internalStyle, style);
}

this.classes fehlt auch in der Methode render, wird aber in einem späteren Abschnitt behandelt. Neben der fehlenden Getter-Methode this.classes müssen noch Teile des TopAppBar implementiert werden, bevor die obere App-Leiste korrekt gerendert werden kann.

In der oberen App-Leiste fehlen die folgenden Teile der React-Komponente:

  • Eine initialisierte Grundlage
  • Adaptermethoden zur Übergabe an die Grundlage
  • JSX-Markup
  • Variantenverwaltung (fest, kurz, immer minimiert, deutlich sichtbar)

Der Ansatz

  1. Implementieren Sie die Adapter-Methoden.
  2. Initialisieren Sie die Foundation in der componentDidMount.
  3. Rufen Sie die Methode Foundation.destroy in der componentWillUnmount auf.
  4. Richten Sie die Variantenverwaltung mithilfe einer Getter-Methode ein, die geeignete Klassennamen kombiniert.

4. Adaptermethoden implementieren

Die nicht-Framework-JS-Komponente TopAppBar implementiert die folgenden Adapter-Methoden, die hier ausführlich aufgeführt sind:

  • hasClass()
  • addClass()
  • removeClass()
  • registerNavigationIconInteractionHandler()
  • deregisterNavigationIconInteractionHandler()
  • notifyNavigationIconClicked()
  • setStyle()
  • getTopAppBarHeight()
  • registerScrollHandler()
  • deregisterScrollHandler()
  • registerResizeHandler()
  • deregisterResizeHandler()
  • getViewportScrollY()
  • getTotalActionItems()

Da React synthetische Ereignisse und andere Best Practices für die Programmierung sowie -muster hat, müssen die Adapter-Methoden neu implementiert werden.

Adapter-Getter-Methode

Fügen Sie in der Datei TopAppBar.js die folgende JavaScript-Methode zu TopAppBar hinzu:

get adapter() {
  const {actionItems} = this.props;

  return {
    hasClass: (className) => this.classes.split(' ').includes(className),
    addClass: (className) => this.setState({classList: this.state.classList.add(className)}),
    removeClass: (className) => {
      const {classList} = this.state;
      classList.delete(className);
      this.setState({classList});
    },
    setStyle: this.setStyle,
    getTopAppBarHeight: () => this.topAppBarElement.current.clientHeight,
    registerScrollHandler: (handler) => window.addEventListener('scroll', handler),
    deregisterScrollHandler: (handler) => window.removeEventListener('scroll', handler),
    registerResizeHandler: (handler) => window.addEventListener('resize', handler),
    deregisterResizeHandler: (handler) => window.removeEventListener('resize', handler),
    getViewportScrollY: () => window.pageYOffset,
    getTotalActionItems: () => actionItems && actionItems.length,
  };
}

Die Adapter-APIs für die Registrierung von Scroll- und Größen-Ereignissen sind identisch mit der Nicht-Framework-JS-Version implementiert, da React kein synthetisches Ereignis zum Scrollen oder Ändern der Größe hat und auf das native DOM-Ereignissystem verweist. getViewPortScrollY muss außerdem auf das native DOM verweisen, da es eine Funktion im window-Objekt ist, das nicht in der API von React enthalten ist. Die Adapterimplementierungen unterscheiden sich je nach Framework.

Sie werden feststellen, dass this.setStyle fehlt, das von der get adapter-Methode aufgerufen wird. Fügen Sie in der Datei TopAppBar.js der Klasse TopAppBar die fehlende JavaScript-Methode hinzu:

setStyle = (varName, value) => {
  const updatedStyle = Object.assign({}, this.state.style);
  updatedStyle[varName] = value;
  this.setState({style: updatedStyle});
}

Sie haben gerade den Adapter implementiert. Möglicherweise werden an dieser Stelle Fehler in Ihrer Konsole angezeigt, da die vollständige Implementierung noch nicht abgeschlossen ist. Im nächsten Abschnitt erfahren Sie, wie Sie CSS-Klassen hinzufügen und entfernen.

5. Komponentenmethoden implementieren

Varianten und Klassen verwalten

React hat keine API zum Verwalten von Klassen. Fügen Sie die Statusvariable classList hinzu, um die CSS-Klassenmethoden des nativen JavaScript-Codes zu imitieren. In TopAppBar gibt es drei Code-Snippets, die mit CSS-Klassen interagieren:

  1. Komponente „<TopAppBar />“ über das Attribut „className
  2. Die Methode Adapter über addClass oder removeClass.
  3. Hartcodiert in der React-Komponente <TopAppBar />.

Fügen Sie zuerst den folgenden Import oben in TopAppBar.js unterhalb der vorhandenen Importe hinzu:

import classnames from 'classnames';

Fügen Sie dann den folgenden Code in die Klassendeklaration der Komponente TopAppBar ein:

export default class TopAppBar extends React.Component {
  constructor(props) {
    super(props);
    this.topAppBarElement = React.createRef();
  }

  state = {
    classList: new Set(),
    style: {},
  };

  get classes() {
    const {classList} = this.state;
    const {
      alwaysCollapsed,
      className,
      short,
      fixed,
      prominent,
    } = this.props;

    return classnames('mdc-top-app-bar', Array.from(classList), className, {
      'mdc-top-app-bar--fixed': fixed,
      'mdc-top-app-bar--short': short,
      'mdc-top-app-bar--short-collapsed': alwaysCollapsed,
      'mdc-top-app-bar--prominent': prominent,
    });
  }

  ... 
}

Wenn Sie http://localhost:8080 aufrufen, können Sie mit den Steuerelementen die Klassennamen im DOM aktivieren bzw. deaktivieren.

Mit diesem Code kann TopAppBar von vielen Entwicklern verwendet werden. Entwickler können mit der TopAppBar API interagieren, ohne sich um die Implementierungsdetails von CSS-Klassen kümmern zu müssen.

Sie haben den Adapter jetzt erfolgreich implementiert. Im nächsten Abschnitt erfahren Sie, wie Sie eine Foundation instanziieren.

Komponente montieren und trennen

Die Instanziierung Foundation erfolgt in der Methode componentDidMount.

Importieren Sie zuerst die Grundlagen der MDC Top App Bar. Fügen Sie dazu den folgenden Import nach den vorhandenen Importen in TopAppBar.js hinzu:

import {MDCTopAppBarFoundation, MDCFixedTopAppBarFoundation, MDCShortTopAppBarFoundation} from '@material/top-app-bar';

Fügen Sie als Nächstes den folgenden JavaScript-Code in die TopAppBar-Klasse ein:

export default class TopAppBar extends React.Component {
 
  ... 

  foundation_ = null;

  componentDidMount() {
    this.initializeFoundation();
  }

  componentWillUnmount() {
    this.foundation_.destroy();
  }

  initializeFoundation = () => {
    if (this.props.short) {
      this.foundation_ = new MDCShortTopAppBarFoundation(this.adapter);
    } else if (this.props.fixed) {
      this.foundation_ = new MDCFixedTopAppBarFoundation(this.adapter);
    } else {
      this.foundation_ = new MDCTopAppBarFoundation(this.adapter);
    }

    this.foundation_.init();
  }
 
  ... 

}

Eine gute Codierungspraxis für React besteht darin, propTypes und defaultProps zu definieren. Fügen Sie den folgenden Import nach den vorhandenen Importen in TopAppBar.js hinzu:

import PropTypes from 'prop-types';

Fügen Sie dann unten in TopAppBar.js (nach der Komponentenklasse) den folgenden Code ein:

import PropTypes from 'prop-types';

TopAppBar.propTypes = {
  alwaysCollapsed: PropTypes.bool,
  short: PropTypes.bool,
  fixed: PropTypes.bool,
  prominent: PropTypes.bool,
  title: PropTypes.string,
  actionItems: PropTypes.arrayOf(PropTypes.element),
  navIcon: PropTypes.element,
};

TopAppBar.defaultProps = {
  alwaysCollapsed: false,
  short: false,
  fixed: false,
  prominent: false,
  title: '',
  actionItems: null,
  navIcon: null,
};

Sie haben die Top App Bar React-Komponente erfolgreich implementiert. Wenn Sie http://localhost:8080 aufrufen, können Sie die Demoseite ausprobieren. Die Demoseite funktioniert genauso wie die Demoseite von MDC Web. Die Demoseite sollte so aussehen:

3d983b98c2092e7a.png

6. Zusammenfassung

In diesem Tutorial haben Sie erfahren, wie Sie die Foundation von MDC Web für die Verwendung in einer React-Anwendung verpacken können. Es gibt einige Bibliotheken auf GitHub und npm, die MDC-Webkomponenten umschließen, wie unter In Frameworks integrieren beschrieben. Wir empfehlen dir, diese Liste zu verwenden. Diese Liste enthält neben React auch weitere Frameworks wie Angular und Vue.

In diesem Tutorial sehen wir unsere Entscheidung, den MDC-Webcode in drei Teile aufzuteilen: die Grundlage, den Adapter und die Komponente. Diese Architektur ermöglicht es Komponenten, gemeinsamen Code zu nutzen, während sie mit allen Frameworks arbeiten. Vielen Dank, dass du Material Components React ausprobiert hast. Wirf einen Blick auf unsere neue Bibliothek MDC React. Wir hoffen, dieses Codelab hat Ihnen gefallen.

Ich konnte dieses Codelab mit angemessenem Zeit- und Arbeitsaufwand abschließen

<ph type="x-smartling-placeholder"></ph> Stimme vollkommen zu Stimme zu Weder zufrieden noch unzufrieden Stimme nicht zu Stimme überhaupt nicht zu

Ich möchte Material Components weiterhin verwenden.

<ph type="x-smartling-placeholder"></ph> Stimme vollkommen zu Stimme zu Weder zufrieden noch unzufrieden Stimme nicht zu Stimme überhaupt nicht zu