MDC-112 Web: intégration de MDC aux frameworks Web

1. Introduction

logo_components_color_2x_web_96dp.png

Material Components (MDC) aide les développeurs à implémenter Material Design. Conçu par une équipe d'ingénieurs et de spécialistes de l'expérience utilisateur chez Google, MDC propose des dizaines de composants d'interface utilisateur élégants et fonctionnels. Il est disponible pour Android, iOS, le Web et Flutter.material.io/develop.

MDC Web est conçu pour s'intégrer à n'importe quel framework de front-end, tout en respectant les principes de Material Design. L'atelier de programmation suivant vous explique comment créer un composant React, qui utilise MDC Web comme base. Les principes appris dans cet atelier de programmation peuvent s'appliquer à n'importe quel framework JavaScript.

Fonctionnement de MDC Web

La couche JavaScript de MDC Web comprend trois classes par composant: Component, Foundation et Adapter. Ce modèle offre à MDC Web la flexibilité nécessaire pour s'intégrer aux frameworks de front-end.

La fondation contient la logique métier qui implémente Material Design. L'élément Foundation ne fait référence à aucun élément HTML. Cela nous permet d'extraire la logique d'interaction HTML dans l'adaptateur. Foundation dispose d'un adaptateur.

L'adaptateur est une interface. La Foundation fait référence à l'interface de l'adaptateur pour implémenter la logique métier Material Design. Vous pouvez implémenter l'adaptateur dans différents frameworks tels qu'Angular ou React. Une implémentation d'un adaptateur interagit avec la structure DOM.

Le composant possède une fondation, et son rôle est de :

  1. Implémentez l'adaptateur à l'aide de JavaScript hors framework, et
  2. Fournissez des méthodes publiques qui servent de proxy pour les méthodes de la fondation.

Ce que MDC Web fournit

Chaque package MDC Web est fourni avec un composant, une fondation et un adaptateur. Pour instancier un composant, vous devez transmettre l'élément racine à la méthode constructeur du composant. Le composant implémente un adaptateur qui interagit avec les éléments DOM et HTML. Le composant instancie ensuite la fondation, qui appelle les méthodes de l'adaptateur.

Pour intégrer MDC Web à un framework, vous devez créer votre propre composant dans la langue/syntaxe de ce framework. Le composant du framework met en œuvre l'adaptateur de MDC Web et utilise la fondation de MDC Web.

Objectifs de l'atelier

Cet atelier de programmation montre comment créer un adaptateur personnalisé pour utiliser la logique Foundation afin de créer un composant React Material Design. Il couvre les sujets avancés abordés dans Intégration dans des frameworks. React est utilisé dans cet atelier de programmation comme exemple de framework, mais cette approche peut être appliquée à n'importe quel autre framework.

Dans cet atelier de programmation, vous allez créer la barre d'application supérieure et recréer la page de démonstration de la barre d'application supérieure. La mise en page de la page de démonstration est déjà configurée. Vous pouvez donc commencer à travailler sur la barre d'application supérieure. La barre d'application supérieure comprend les éléments suivants:

  • Icône de navigation
  • Tâches
  • Quatre variantes sont disponibles: Court, toujours réduit, fixe et proéminent.

Ce dont vous avez besoin:

  • Une version récente de Node.js (fournie avec npm, un gestionnaire de paquets JavaScript)
  • L'exemple de code (à télécharger à l'étape suivante)
  • Connaissances de base en HTML, CSS, JavaScript et React

Comment évalueriez-vous votre niveau d'expérience en développement Web ?

Débutant Intermédiaire Expert

2. Configurer l'environnement de développement

Télécharger l'application de départ de l'atelier de programmation

Elle se trouve dans le répertoire material-components-web-codelabs-master/mdc-112/starter.

… ou cloner l'atelier depuis GitHub

Pour cloner cet atelier de programmation à partir de GitHub, exécutez les commandes suivantes :

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

Installer les dépendances du projet

Dans le répertoire de démarrage material-components-web-codelabs/mdc-112/starter, exécutez:

npm install

Vous verrez de nombreuses activités et, à la fin, votre terminal devrait indiquer une installation réussie:

22a33efc2a687408.png

Exécuter l'application de départ

Dans le même répertoire, exécutez:

npm start

webpack-dev-server démarre. Saisissez l'adresse http://localhost:8080/ dans votre navigateur pour afficher la page.

b55c66dd400cf34f.png

Opération réussie. Le code de démarrage de la page de démonstration React de la barre d'application supérieure doit s'exécuter dans votre navigateur. Vous devriez voir un mur de texte lorem ipsum, une zone Commandes (en bas à droite) et une barre d'application supérieure inachevée:

4ca3cf6d216f9290.png

Examiner le code et le projet

Si vous ouvrez votre éditeur de code, le répertoire du projet devrait ressembler à ceci:

e9a3270d6a67c589.png

Ouvrez le fichier App.js et examinez la méthode render, qui inclut le composant <TopAppBar>:

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>
    );
  }

Il s'agit du point d'entrée de TopAppBar dans l'application.

Ouvrez le fichier TopAppBar.js, qui est une classe React Component simple avec une méthode render:

TopAppBar.js

import React from 'react';

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

3. Composition du composant

Dans React, la méthode render génère le code HTML du composant. Le composant de la barre d'application supérieure affichera une balise <header /> et se composera de deux sections principales:

  1. Icône de navigation et section du titre
  2. Section "Icônes d'action"

Si vous avez des questions sur les éléments qui composent la barre d'application supérieure, consultez la documentation sur GitHub.

Modifiez la méthode render() dans TopAppBar.js pour qu'elle se présente comme suit:

  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>
    );
  }

Ce code HTML contient deux éléments de section. Le premier contient une icône de navigation et un titre. Le second contient des icônes d'action.

Ajoutez ensuite la méthode renderActionItems:

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>
  );
}

Un développeur importe TopAppBar dans son application React et transmet des icônes d'action à l'élément TopAppBar. Vous pouvez consulter un exemple de code qui initialise un TopAppBar dans App.js.

La méthode getMergedStyles qui est utilisée dans la méthode render est manquante. Veuillez ajouter la méthode JavaScript suivante à la classe TopAppBar:

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

this.classes est également absent de la méthode render, mais sera abordé dans une section ultérieure. En plus de la méthode getter manquante, this.classes, vous devez encore implémenter des éléments de TopAppBar pour que la barre d'application supérieure puisse s'afficher correctement.

Les éléments du composant React qui sont toujours manquants dans la barre d'application supérieure sont les suivants:

  • Une base initialisée
  • Méthodes de l'adaptateur à transmettre aux éléments de base
  • Balisage JSX
  • Gestion des variantes (fixe, courte, toujours réduite, visible)

La méthode

  1. Implémentez les méthodes Adapter.
  2. Initialisez la fondation dans componentDidMount.
  3. Appelez la méthode Foundation.destroy dans componentWillUnmount.
  4. Établissez la gestion des variantes à l'aide d'une méthode getter qui combine les noms de classe appropriés.

4. Implémenter les méthodes de l'adaptateur

Le composant TopAppBar JavaScript hors framework implémente les méthodes Adapter suivantes (listées en détail ici):

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

React dispose d'événements synthétiques et de différentes bonnes pratiques et tendances de codage. Les méthodes Adapter doivent donc être réimplémentées.

Méthode de getter d'adaptateur

Dans le fichier TopAppBar.js, ajoutez la méthode JavaScript suivante à TopAppBar:

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,
  };
}

Les API d'adaptateur pour l'enregistrement d'événements de défilement et de redimensionnement sont implémentées de manière identique à la version JS sans framework, car React ne dispose d'aucun événement synthétique pour le défilement ou le redimensionnement, et reporte la gestion à l'aide du système d'événements DOM natif. getViewPortScrollY doit également s'appliquer au DOM natif, car il s'agit d'une fonction sur l'objet window, qui ne figure pas dans l'API de React. Les implémentations d'adaptateur sont différentes pour chaque framework.

Vous remarquerez peut-être que this.setStyle est manquant, appelé par la méthode get adapter. Dans le fichier TopAppBar.js, ajoutez la méthode JavaScript manquante à la classe TopAppBar:

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

Vous venez d'implémenter l'adaptateur. Notez qu'il est possible que des erreurs s'affichent dans votre console à ce stade, car l'implémentation complète n'est pas encore terminée. La section suivante vous explique comment ajouter et supprimer des classes CSS.

5. Implémenter des méthodes de composant

Gérer les variantes et les cours

React ne dispose pas d'API pour gérer les classes. Pour imiter les méthodes d'ajout/de suppression de classe CSS JavaScript natives, ajoutez la variable d'état classList. TopAppBar contient trois éléments de code qui interagissent avec les classes CSS:

  1. Composant <TopAppBar /> via la propriété className.
  2. La méthode Adapter via addClass ou removeClass.
  3. Codé en dur dans le composant React <TopAppBar />.

Tout d'abord, ajoutez l'importation suivante en haut de TopAppBar.js, sous les importations existantes:

import classnames from 'classnames';

Ajoutez ensuite le code suivant dans la déclaration de classe du composant TopAppBar:

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,
    });
  }

  ... 
}

Si vous accédez à http://localhost:8080, les cases à cocher "Controls" (Commandes) devraient maintenant activer/désactiver les noms des classes dans le DOM.

Ce code permet à de nombreux développeurs d'utiliser TopAppBar. Les développeurs peuvent interagir avec l'API TopAppBar sans se soucier des détails d'implémentation des classes CSS.

Vous avez maintenant implémenté l'adaptateur. La section suivante vous explique comment instancier une fondation.

Installer et désinstaller le composant

L'instanciation de Foundation se produit dans la méthode componentDidMount.

Commencez par importer les bases de la barre d'application supérieure MDC en ajoutant l'importation suivante après les importations existantes dans TopAppBar.js:

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

Ajoutez ensuite le code JavaScript suivant dans la classe TopAppBar:

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();
  }
 
  ... 

}

Une bonne pratique de codage React consiste à définir propTypes et defaultProps. Ajoutez l'importation suivante après les importations existantes dans TopAppBar.js:

import PropTypes from 'prop-types';

Ajoutez ensuite le code suivant en bas de TopAppBar.js (après la classe Component):

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,
};

Vous venez d'implémenter le composant React de la barre d'application supérieure. Si vous accédez à http://localhost:8080, vous pouvez jouer avec la page de démonstration. La page de démonstration fonctionnera de la même manière que la page de démonstration de MDC Web. La page de démonstration doit se présenter comme suit:

3d983b98c2092e7a.png

6. Conclusion

Dans ce tutoriel, nous avons appris à encapsuler la Foundation de MDC Web pour l'utiliser dans une application React. Sur GitHub et npm, il existe quelques bibliothèques qui encapsulent les composants Web MDC, comme décrit dans la section Intégration dans les frameworks. Nous vous recommandons d'utiliser la liste disponible ici. Cette liste inclut également d'autres frameworks que React, tels que Angular et Vue.

Ce tutoriel met en avant notre décision de diviser le code Web MDC en trois parties : la fondation, l'adaptateur et le composant. Cette architecture permet aux composants de partager du code commun tout en travaillant avec tous les frameworks. Merci d'avoir essayé Material Components React. Veuillez consulter notre nouvelle bibliothèque MDC React. Nous espérons que cet atelier de programmation vous a plu.

La réalisation de cet atelier de programmation m'a demandé un temps et des efforts raisonnables

Tout à fait d'accord D'accord Ni d'accord, ni pas d'accord Pas d'accord Pas du tout d'accord

Je souhaite continuer à utiliser Material Components

Tout à fait d'accord D'accord Neutre Pas d'accord Pas du tout d'accord