Web MDC-112: Mengintegrasikan MDC dengan Framework Web

1. Pengantar

logo_components_color_2x_web_96dp.png

Komponen Material (MDC) membantu developer menerapkan Desain Material. Dibuat oleh tim engineer dan desainer UX di Google, MDC memiliki banyak komponen UI yang indah dan fungsional serta tersedia untuk Android, iOS, web, dan Flutter.material.io/develop

MDC Web dirancang untuk berintegrasi ke dalam framework frontend apa pun sekaligus mempertahankan prinsip Desain Material. Codelab berikut akan memandu Anda dalam mem-build Komponen React, yang menggunakan MDC Web sebagai fondasinya. Prinsip yang dipelajari dalam codelab ini dapat diterapkan ke framework JavaScript apa pun.

Cara MDC Web dibuat

Lapisan JavaScript MDC Web terdiri dari tiga class per komponen: Component, Foundation, dan Adapter. Pola ini memberi MDC Web fleksibilitas untuk berintegrasi dengan framework frontend.

Dasar berisi logika bisnis yang mengimplementasikan Desain Material. Foundation tidak mereferensikan elemen HTML apa pun. Hal ini memungkinkan kita memisahkan logika interaksi HTML ke dalam Adaptor. Dasar memiliki Adaptor.

Adapter adalah antarmuka. Antarmuka Adaptor dirujuk oleh Foundation untuk menerapkan logika bisnis Desain Material. Anda dapat menerapkan Adapter di berbagai framework seperti Angular atau React. Implementasi Adaptor berinteraksi dengan struktur DOM.

Komponen memiliki Dasar, dan perannya adalah untuk

  1. Terapkan Adaptor, menggunakan JavaScript non-framework, dan
  2. Menyediakan metode publik yang melakukan proxy ke metode di Foundation.

Yang disediakan MDC Web

Setiap paket di MDC Web dilengkapi dengan Komponen, Dasar, dan Adaptor. Untuk membuat instance Komponen, Anda harus meneruskan elemen root ke metode konstruktor Komponen. Komponen mengimplementasikan Adaptor, yang berinteraksi dengan elemen DOM dan HTML. Komponen kemudian membuat instance Foundation, yang memanggil metode Adapter.

Untuk mengintegrasikan MDC Web ke dalam framework, Anda perlu membuat Komponen sendiri dalam bahasa/sintaksis framework tersebut. Komponen framework mengimplementasikan Adaptor MDC Web dan menggunakan Dasar MDC Web.

Yang akan Anda bangun

Codelab ini menunjukkan cara mem-build Adaptor kustom untuk menggunakan logika Dasar guna mendapatkan Komponen React Desain Material. Panduan ini mencakup topik lanjutan yang terdapat dalam artikel Mengintegrasikan ke Framework. React digunakan dalam codelab ini sebagai contoh framework, tetapi pendekatan ini dapat diterapkan ke framework lainnya.

Dalam codelab ini, Anda akan mem-build Panel Aplikasi Atas dan membuat ulang halaman demo panel aplikasi atas. Tata letak halaman demo sudah disiapkan sehingga Anda dapat mulai mengerjakan Panel Aplikasi Atas. Panel Aplikasi Atas akan mencakup:

  • Ikon navigasi
  • Item tindakan
  • Ada 4 varian yang tersedia: varian pendek, selalu diciutkan, tetap, dan jelas

Yang Anda butuhkan:

  • Node.js versi terbaru (yang dipaketkan dengan npm, pengelola paket JavaScript)
  • Kode contoh (akan didownload di langkah berikutnya)
  • Pengetahuan dasar tentang HTML, CSS, JavaScript, dan React

Bagaimana Anda menilai tingkat pengalaman Anda dengan pengembangan web?

Pemula Menengah Mahir

2. Menyiapkan lingkungan pengembangan

Mendownload aplikasi codelab awal

Aplikasi awal terletak di direktori material-components-web-codelabs-master/mdc-112/starter.

...atau meng-clone codelab dari GitHub

Untuk meng-clone codelab ini dari GitHub, jalankan perintah berikut:

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

Menginstal dependensi project

Dari direktori awal material-components-web-codelabs/mdc-112/starter, jalankan:

npm install

Anda akan melihat banyak aktivitas dan pada akhirnya, terminal akan menampilkan penginstalan yang berhasil:

22a33efc2a687408.png

Menjalankan aplikasi awal

Di direktori yang sama, jalankan:

npm start

webpack-dev-server akan dimulai. Arahkan browser ke http://localhost:8080/ untuk melihat halaman.

b55c66dd400cf34f.png

Berhasil! Kode awal untuk halaman Demo React Panel Aplikasi Teratas harus berjalan di browser Anda. Anda akan melihat dinding teks lorem ipsum, kotak Kontrol (kanan bawah), dan Panel Aplikasi Atas yang belum selesai:

4ca3cf6d216f9290.png

Lihat kode dan project

Jika Anda membuka editor kode, direktori project akan terlihat seperti ini:

e9a3270d6a67c589.png

Buka file App.js dan lihat metode render yang menyertakan Komponen <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>
    );
  }

Ini adalah titik entri untuk TopAppBar dalam aplikasi.

Buka file TopAppBar.js yang merupakan class Component React murni dengan metode render:

TopAppBar.js

import React from 'react';

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

3. Komposisi komponen

Di React, metode render menghasilkan output HTML Komponen. Komponen Panel Aplikasi Atas akan merender tag <header />, dan akan terdiri dari 2 bagian utama:

  1. Ikon navigasi dan bagian judul
  2. Bagian ikon tindakan

Jika Anda memiliki pertanyaan tentang elemen yang membentuk Panel Aplikasi Atas, buka dokumentasi di GitHub.

Ubah metode render() di TopAppBar.js agar terlihat seperti ini:

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

Ada dua elemen bagian dalam HTML ini. Yang pertama berisi ikon dan judul navigasi. Baris kedua berisi ikon tindakan.

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

Developer akan mengimpor TopAppBar ke aplikasi React dan meneruskan ikon tindakan ke elemen TopAppBar. Anda dapat melihat contoh kode yang melakukan inisialisasi TopAppBar di App.js.

Metode getMergedStyles tidak ada, yang digunakan dalam metode render. Tambahkan metode JavaScript berikut ke class TopAppBar:

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

this.classes juga tidak ada dalam metode render, tetapi akan dibahas di bagian selanjutnya. Selain metode pengambil yang hilang, this.classes, masih ada bagian TopAppBar yang perlu Anda terapkan sebelum Panel Aplikasi Atas dapat dirender dengan benar.

Bagian Komponen React yang masih belum ada di Panel Aplikasi Atas adalah:

  • Dasar yang diinisialisasi
  • Metode adaptor untuk diteruskan ke fondasi
  • Markup JSX
  • Pengelolaan varian (tetap, singkat, selalu diciutkan, jelas)

Pendekatan

  1. Implementasikan metode Adaptor.
  2. Lakukan inisialisasi Foundation di componentDidMount.
  3. Panggil metode Foundation.destroy di componentWillUnmount.
  4. Buat pengelolaan varian melalui metode pengambil yang menggabungkan nama class yang sesuai.

4. Mengimplementasikan metode Adaptor

Komponen TopAppBar JS non-framework menerapkan metode Adaptor berikut (tercantum secara mendetail di sini):

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

Karena React memiliki peristiwa sintetis serta berbagai praktik dan pola coding terbaik, metode Adapter perlu diterapkan kembali.

Metode Pengambil Adaptor

Di file TopAppBar.js, tambahkan metode JavaScript berikut ke 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,
  };
}

API adaptor untuk pendaftaran peristiwa scroll dan ubah ukuran diterapkan secara identik dengan versi JS non-framework, karena React tidak memiliki peristiwa sintetis untuk men-scroll atau mengubah ukuran dan mematuhi sistem peristiwa DOM native. getViewPortScrollY juga perlu ditunda ke DOM native karena merupakan fungsi pada objek window, yang tidak ada di API React. Implementasi adaptor akan berbeda untuk setiap framework.

Anda mungkin melihat this.setStyle tidak ada, yang dipanggil oleh metode get adapter. Dalam file TopAppBar.js, tambahkan metode JavaScript yang tidak ada ke class TopAppBar:

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

Anda baru saja menerapkan Adaptor. Perhatikan bahwa Anda mungkin melihat error di konsol pada tahap ini karena implementasi penuh belum selesai. Bagian berikutnya akan memandu Anda cara menambahkan dan menghapus class CSS.

5. Mengimplementasikan metode Komponen

Mengelola Varian dan Kelas

React tidak memiliki API untuk mengelola class. Untuk meniru metode class tambahkan/hapus pada JavaScript native, tambahkan variabel status classList. Ada tiga bagian kode di TopAppBar yang berinteraksi dengan class CSS:

  1. Komponen <TopAppBar /> melalui properti className.
  2. Metode Adaptor melalui addClass atau removeClass.
  3. Di-hardcode dalam Komponen React <TopAppBar />.

Pertama, tambahkan impor berikut di bagian atas TopAppBar.js, di bawah impor yang ada:

import classnames from 'classnames';

Kemudian, tambahkan kode berikut di dalam deklarasi class Komponen 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,
    });
  }

  ... 
}

Jika Anda membuka http://localhost:8080, kotak centang Kontrol kini akan mengaktifkan/menonaktifkan nama class dari DOM.

Kode ini membuat TopAppBar dapat digunakan oleh banyak developer. Developer dapat berinteraksi dengan TopAppBar API, tanpa perlu mengkhawatirkan detail implementasi class CSS.

Anda kini telah berhasil mengimplementasikan Adaptor. Bagian berikutnya akan memandu Anda membuat instance Foundation.

Memasang dan Melepas Komponen

Pembuatan instance Foundation terjadi dalam metode componentDidMount.

Pertama, impor fondasi MDC Top App Bar dengan menambahkan impor berikut setelah impor yang ada di TopAppBar.js:

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

Selanjutnya, tambahkan kode JavaScript berikut ke class 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();
  }
 
  ... 

}

Salah satu praktik coding React yang baik adalah menentukan propTypes dan defaultProps. Tambahkan impor berikut setelah impor yang ada di TopAppBar.js:

import PropTypes from 'prop-types';

Kemudian, tambahkan kode berikut ke bagian bawah TopAppBar.js (setelah class Komponen):

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

Anda kini telah berhasil menerapkan Komponen React Panel Aplikasi Atas. Jika membuka http://localhost:8080, Anda dapat bermain dengan halaman demo. Halaman demo akan berfungsi sama seperti halaman demo MDC Web. Halaman demo akan terlihat seperti ini:

3d983b98c2092e7a.png

6. Rangkuman

Dalam tutorial ini, kita telah membahas cara menggabungkan Fondasi Web MDC untuk digunakan dalam aplikasi React. Ada beberapa library di GitHub dan npm yang menggabungkan Komponen Web MDC seperti yang dijelaskan dalam Mengintegrasikan ke Framework. Sebaiknya gunakan daftar yang ada di sini. Daftar ini juga mencakup framework lain selain React seperti Angular dan Vue.

Tutorial ini menyoroti keputusan kami untuk membagi kode Web MDC menjadi 3 bagian, yaitu Dasar, Adaptor, dan Komponen. Arsitektur ini memungkinkan komponen berbagi kode umum saat bekerja dengan semua framework. Terima kasih telah mencoba Material Components React dan lihat library baru kami, MDC React. Kami harap Anda menikmati codelab ini.

Saya dapat menyelesaikan codelab ini dengan upaya dan dalam durasi waktu yang wajar

Sangat setuju Setuju Netral Tidak setuju Sangat tidak setuju

Saya ingin terus menggunakan Komponen Material pada masa mendatang

Sangat setuju Setuju Netral Tidak setuju Sangat tidak setuju