1. Wprowadzenie
Komponenty Material Design (MDC) pomagają deweloperom wdrażać Material Design. MDC zostało stworzone przez zespół inżynierów i projektantów UX w Google. Zawiera dziesiątki atrakcyjnych i funkcjonalnych komponentów interfejsu, które są dostępne na platformach Android, iOS, internetowej i Flutter.material.io/develop |
MDC Web zostało zaprojektowane tak, aby można je było zintegrować z dowolną platformą front-endową przy zachowaniu zasad Material Design. Z tego ćwiczenia dowiesz się, jak utworzyć komponent React, który korzysta z MDC Web jako podstawy. Zasady poznane w tym ćwiczeniu możesz zastosować w przypadku dowolnej platformy JavaScript.
Jak jest zbudowana biblioteka MDC Web
Warstwa JavaScript MDC Web składa się z 3 klas na komponent: Component, Foundation i Adapter. Ten wzorzec zapewnia MDC Web elastyczność w zakresie integracji z platformami frontendowymi.
Foundation zawiera logikę biznesową, która implementuje Material Design. Fundacja nie odwołuje się do żadnych elementów HTML. Dzięki temu możemy wyodrębnić logikę interakcji HTML do adaptera. Fundacja ma adapter.
Adapter to interfejs. Interfejs Adapter jest używany przez Foundation do implementowania logiki biznesowej Material Design. Adapter możesz zaimplementować na różnych platformach, takich jak Angular czy React. Implementacja adaptera wchodzi w interakcje ze strukturą DOM.
Komponent ma podstawę, a jego zadaniem jest
- Zaimplementuj adapter za pomocą JavaScriptu bez użycia platformy.
- Udostępnij publiczne metody, które przekazują wywołania do metod w Foundation.
Co oferuje MDC Web
Każdy pakiet w MDC Web zawiera komponent, podstawę i adapter. Aby utworzyć instancję komponentu, musisz przekazać do metody konstruktora komponentu główny element. Komponent implementuje adapter, który wchodzi w interakcję z elementami DOM i HTML. Komponent tworzy następnie instancję Foundation, która wywołuje metody Adapter.
Aby zintegrować MDC Web z frameworkiem, musisz utworzyć własny komponent w języku lub składni tego frameworka. Komponent Component platformy implementuje Adapter MDC Web i korzysta z Foundation MDC Web.
Co utworzysz
To ćwiczenie pokazuje, jak utworzyć niestandardowy adapter, aby użyć logiki Foundation do utworzenia komponentu React Material Design. Obejmuje zaawansowane tematy, które znajdziesz w sekcji Integracja z platformami. W tym ćwiczeniu w Codelabs jako przykładowa platforma używany jest React, ale to podejście można zastosować w przypadku dowolnej innej platformy.
W tym ćwiczeniu zbudujesz górny pasek aplikacji i odtworzysz stronę demonstracyjną górnego paska aplikacji. Układ strony demonstracyjnej jest już skonfigurowany, więc możesz zacząć pracę nad górnym paskiem aplikacji. Górny pasek aplikacji będzie zawierać:
- Ikona nawigacji
- Action items
- Dostępne są 4 warianty: krótki, zawsze zwinięty, stały i wyróżniony.
Co będzie Ci potrzebne:
- Najnowsza wersja Node.js (w pakiecie z npm, menedżerem pakietów JavaScript)
- przykładowy kod (do pobrania w następnym kroku);
- Podstawowa znajomość języków HTML, CSS, JavaScript i React
Jak oceniasz swój poziom doświadczenia w zakresie tworzenia stron internetowych?
2. Konfigurowanie środowiska deweloperskiego
Pobierz aplikację do ćwiczeń z programowania
Aplikacja startowa znajduje się w katalogu material-components-web-codelabs-master/mdc-112/starter.
...lub sklonuj go z GitHub
Aby skopiować ten codelab z GitHuba, uruchom te polecenia:
git clone https://github.com/material-components/material-components-web-codelabs
cd material-components-web-codelabs/mdc-112/starter
Instalowanie zależności projektu
W katalogu początkowym material-components-web-codelabs/mdc-112/starter uruchom:
npm install
Zobaczysz wiele działań, a na końcu w terminalu powinien pojawić się komunikat o pomyślnej instalacji:

Uruchom aplikację startową
W tym samym katalogu uruchom:
npm start
Rozpocznie się webpack-dev-server. Aby wyświetlić stronę, otwórz w przeglądarce adres http://localhost:8080/.

Gotowe! Kod startowy strony demonstracyjnej komponentu Top App Bar w React powinien być uruchomiony w przeglądarce. Powinna się wyświetlić ściana tekstu lorem ipsum, pole Controls (w prawym dolnym rogu) i nieukończony górny pasek aplikacji:

Sprawdź kod i projekt
Jeśli otworzysz edytor kodu, katalog projektu powinien wyglądać mniej więcej tak:

Otwórz plik App.js i zapoznaj się z metodą render, która zawiera komponent <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>
);
}
To punkt wejścia dla TopAppBar w aplikacji.
Otwórz plik TopAppBar.js, który jest prostą klasą React Component z metodą render:
TopAppBar.js
import React from 'react';
export default class TopAppBar extends React.Component {
render() {
return (
<header>
TOP APP BAR
</header>
);
}
}
3. Skład komponentu
W React metoda render generuje kod HTML komponentu. Komponent górnego paska aplikacji renderuje tag <header /> i składa się z 2 głównych sekcji:
- Sekcja ikony i tytułu nawigacji
- Sekcja ikon czynności
Jeśli masz pytania dotyczące elementów, z których składa się górny pasek aplikacji, zapoznaj się z dokumentacją na GitHub.
Zmodyfikuj metodę render() w TopAppBar.js, aby wyglądała tak:
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>
);
}
W tym kodzie HTML znajdują się 2 elementy sekcji. Pierwszy zawiera ikonę nawigacji i tytuł. Drugi zawiera ikony działań.
Następnie dodaj metodę 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>
);
}
Deweloper zaimportuje TopAppBar do aplikacji React i przekaże ikony działań do elementu TopAppBar. Przykładowy kod inicjujący TopAppBar znajdziesz w App.js.
Brak metody getMergedStyles, która jest używana w metodzie render. Dodaj do klasy TopAppBar tę metodę JavaScript:
getMergedStyles = () => {
const {style} = this.props;
const {style: internalStyle} = this.state;
return Object.assign({}, internalStyle, style);
}
Tagu this.classes brakuje też w metodzie render, ale omówimy go w dalszej części. Oprócz brakującej metody pobierania this.classes musisz jeszcze zaimplementować fragmenty TopAppBar, aby górny pasek aplikacji mógł się prawidłowo renderować.
Elementy komponentu React, których nadal brakuje na górnym pasku aplikacji:
- zainicjowany model podstawowy,
- Metody adaptera do przekazywania do podstawy
- Znaczniki JSX
- Zarządzanie wariantami (stałe, krótkie, zawsze zwinięte, wyróżnione)
Realizacja
- Zaimplementuj metody Adapter.
- Zainicjuj Foundation w
componentDidMount. - Wywołaj metodę Foundation.destroy w
componentWillUnmount. - Ustal zarządzanie wariantami za pomocą metody pobierającej, która łączy odpowiednie nazwy klas.
4. Implementowanie metod adaptera
Niezależny od platformy JS TopAppBar Component implementuje te metody Adapter (szczegółowe informacje znajdziesz tutaj):
hasClass()addClass()removeClass()registerNavigationIconInteractionHandler()deregisterNavigationIconInteractionHandler()notifyNavigationIconClicked()setStyle()getTopAppBarHeight()registerScrollHandler()deregisterScrollHandler()registerResizeHandler()deregisterResizeHandler()getViewportScrollY()getTotalActionItems()
Ze względu na zdarzenia syntetyczne w React oraz inne sprawdzone metody i wzorce kodowania metody adaptera muszą zostać zaimplementowane ponownie.
Metoda pobierania adaptera
W pliku TopAppBar.js dodaj do elementu TopAppBar tę metodę JavaScript:
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,
};
}
Interfejsy API adaptera do rejestrowania zdarzeń przewijania i zmiany rozmiaru są zaimplementowane identycznie jak w przypadku wersji JS bez frameworka, ponieważ React nie ma żadnego syntetycznego zdarzenia do przewijania lub zmiany rozmiaru i odwołuje się do natywnego systemu zdarzeń DOM. Metoda getViewPortScrollY musi też odwoływać się do natywnego modelu DOM, ponieważ jest funkcją obiektu window, który nie znajduje się w interfejsie API Reacta. Implementacje adaptera będą się różnić w zależności od platformy.
Możesz zauważyć, że brakuje this.setStyle, które jest wywoływane przez metodę get adapter. W pliku TopAppBar.js dodaj brakującą metodę JavaScript do klasy TopAppBar:
setStyle = (varName, value) => {
const updatedStyle = Object.assign({}, this.state.style);
updatedStyle[varName] = value;
this.setState({style: updatedStyle});
}
Właśnie wdrożono adapter. Pamiętaj, że na tym etapie w konsoli mogą pojawiać się błędy, ponieważ pełne wdrożenie nie zostało jeszcze ukończone. W następnej sekcji dowiesz się, jak dodawać i usuwać klasy CSS.
5. Implementowanie metod komponentu
Zarządzanie odmianami i zajęciami
React nie ma interfejsu API do zarządzania klasami. Aby naśladować metody dodawania i usuwania klas CSS w natywnym JavaScript, dodaj zmienną stanu classList. W TopAppBar znajdują się 3 fragmenty kodu, które działają z klasami CSS:
<TopAppBar />za pomocą właściwościclassName.- Metoda przejściówki przez
addClasslubremoveClass. - Zakodowane na stałe w
<TopAppBar />React Component.
Najpierw dodaj ten import u góry pliku TopAppBar.js, pod istniejącymi importami:
import classnames from 'classnames';
Następnie dodaj ten kod w deklaracji klasy komponentu 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,
});
}
...
}
Jeśli przejdziesz na stronę http://localhost:8080, pola wyboru w sekcji Controls powinny teraz włączać i wyłączać nazwy klas w DOM.
Ten kod sprawia, że TopAppBar jest dostępny dla wielu deweloperów. Deweloperzy mogą korzystać z interfejsu TopAppBar API bez martwienia się o szczegóły implementacji klas CSS.
Adapter został wdrożony. W następnej sekcji dowiesz się, jak utworzyć instancję klasy Foundation.
Montowanie i odmontowywanie komponentu
Instancja Foundation jest tworzona w metodzie componentDidMount.
Najpierw zaimportuj podstawy komponentu MDC Top App Bar, dodając ten import po istniejących importach w pliku TopAppBar.js:
import {MDCTopAppBarFoundation, MDCFixedTopAppBarFoundation, MDCShortTopAppBarFoundation} from '@material/top-app-bar';
Następnie dodaj ten kod JavaScript do klasy 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();
}
...
}
Jedną z dobrych praktyk kodowania w React jest definiowanie propTypes i defaultProps. Po istniejących instrukcjach importu w pliku TopAppBar.js dodaj ten import:
import PropTypes from 'prop-types';
Następnie dodaj ten kod na dole pliku TopAppBar.js (po klasie 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,
};
Komponent React Top App Bar został wdrożony. Jeśli otworzysz stronę http://localhost:8080, możesz wypróbować stronę demonstracyjną. Strona demonstracyjna będzie działać tak samo jak strona demonstracyjna MDC Web. Strona demonstracyjna powinna wyglądać tak:

6. Podsumowanie
W tym samouczku pokazaliśmy, jak opakować Foundation MDC Web, aby można było używać go w aplikacji React. Na platformach GitHub i npm jest kilka bibliotek, które opakowują komponenty internetowe MDC zgodnie z opisem w sekcji Integracja z platformami. Zalecamy korzystanie z listy dostępnej tutaj. Lista obejmuje też inne platformy oprócz Reacta, takie jak Angular i Vue.
W tym samouczku wyjaśniamy, dlaczego podzieliliśmy kod MDC Web na 3 części: Foundation, Adapter i Component. Ta architektura umożliwia komponentom udostępnianie wspólnego kodu przy jednoczesnej współpracy ze wszystkimi platformami. Dziękujemy za wypróbowanie komponentów Material Components React. Zapoznaj się z naszą nową biblioteką MDC React. Mamy nadzieję, że to ćwiczenie było dla Ciebie przydatne.