1. Giới thiệu
Thành phần Material (MDC) giúp nhà phát triển triển khai Material Design. Được tạo bởi một nhóm kỹ sư và nhà thiết kế trải nghiệm người dùng tại Google, MDC có hàng chục thành phần giao diện người dùng đẹp mắt và có chức năng, đồng thời có sẵn cho Android, iOS, web và Flutter.material.io/develop |
MDC Web được thiết kế để tích hợp vào mọi khung giao diện người dùng trong khi vẫn tuân thủ các nguyên tắc của Material Design. Lớp học lập trình sau đây hướng dẫn bạn cách tạo một Thành phần React, sử dụng MDC Web làm nền tảng. Bạn có thể áp dụng các nguyên tắc đã học trong lớp học lập trình này cho mọi khung JavaScript.
Cách tạo MDC Web
Lớp JavaScript của MDC Web bao gồm 3 lớp cho mỗi thành phần: Component, Foundation và Adapter. Mẫu này giúp MDC Web có thể linh hoạt tích hợp với các khung giao diện người dùng.
Foundation (Nền tảng) chứa logic nghiệp vụ triển khai Material Design. Foundation không tham chiếu đến bất kỳ phần tử HTML nào. Việc này cho phép chúng ta trừu tượng hoá logic tương tác HTML thành Adapter. Foundation có một Adapter.
Adapter là một giao diện. Foundation tham chiếu đến giao diện Adapter để triển khai logic nghiệp vụ Material Design. Bạn có thể triển khai Adapter trong nhiều khung hình như Angular hoặc React. Việc triển khai một Bộ điều hợp sẽ tương tác với cấu trúc DOM.
Component có một Foundation và vai trò của thành phần này là
- Triển khai Adapter bằng JavaScript không thuộc khung và
- Cung cấp các phương thức công khai để chuyển đến các phương thức trong Foundation.
Những gì MDC Web cung cấp
Mọi gói trong MDC Web đều đi kèm với một Thành phần, Nền tảng và Bộ chuyển đổi. Để tạo thực thể Component, bạn phải truyền element gốc vào phương thức của hàm khởi tạo Component. Thành phần triển khai một Bộ chuyển đổi, tương tác với DOM và các phần tử HTML. Sau đó, Component sẽ khởi tạo Foundation, gọi các phương thức Adapter.
Để tích hợp MDC Web vào một khung, bạn cần tạo Thành phần của riêng mình bằng ngôn ngữ/cú pháp của khung đó. Component của khung triển khai Adapter của MDC Web và sử dụng Foundation của MDC Web.
Sản phẩm bạn sẽ tạo ra
Lớp học lập trình này minh hoạ cách tạo một Adapter tuỳ chỉnh để sử dụng logic Foundation nhằm đạt được một Thành phần React theo Material Design. Nội dung này đề cập đến các chủ đề nâng cao có trong phần Tích hợp vào các khung. React được dùng trong lớp học lập trình này làm một ví dụ về khung, nhưng bạn có thể áp dụng phương pháp này cho bất kỳ khung nào khác.
Trong lớp học lập trình này, bạn sẽ tạo Thanh ứng dụng trên cùng và tạo lại trang minh hoạ của thanh ứng dụng trên cùng. Bố cục trang minh hoạ đã được thiết lập để bạn có thể bắt đầu làm việc trên Thanh ứng dụng trên cùng. Thanh ứng dụng trên cùng sẽ bao gồm:
- Biểu tượng chỉ đường
- Action items
- Có 4 biến thể: Short, luôn thu gọn, cố định và nổi bật
Những thứ bạn cần:
- Một phiên bản gần đây của Node.js (đi kèm với npm, một trình quản lý gói JavaScript)
- Mã mẫu (sẽ được tải xuống ở bước tiếp theo)
- Kiến thức cơ bản về HTML, CSS, JavaScript và React
Bạn đánh giá thế nào về trình độ của mình trong lĩnh vực phát triển web?
2. Thiết lập môi trường phát triển
Tải ứng dụng khởi đầu của lớp học lập trình xuống
Ứng dụng khởi đầu nằm trong thư mục material-components-web-codelabs-master/mdc-112/starter.
...hoặc sao chép từ GitHub
Để sao chép lớp học lập trình này từ GitHub, hãy chạy các lệnh sau:
git clone https://github.com/material-components/material-components-web-codelabs
cd material-components-web-codelabs/mdc-112/starter
Cài đặt các phần phụ thuộc của dự án
Trong thư mục khởi đầu material-components-web-codelabs/mdc-112/starter, hãy chạy:
npm install
Bạn sẽ thấy nhiều hoạt động và cuối cùng, thiết bị đầu cuối sẽ cho thấy quá trình cài đặt thành công:

Chạy ứng dụng khởi đầu
Trong cùng một thư mục, hãy chạy:
npm start
Gói webpack-dev-server sẽ bắt đầu. Trỏ trình duyệt đến http://localhost:8080/ để xem trang.

Thành công! Mã khởi đầu cho trang minh hoạ Top App Bar React sẽ chạy trong trình duyệt của bạn. Bạn sẽ thấy một bức tường văn bản lorem ipsum, một hộp Controls (Điều khiển) (ở dưới cùng bên phải) và một Thanh ứng dụng trên cùng chưa hoàn chỉnh:

Xem mã và dự án
Nếu bạn mở trình soạn thảo mã, thư mục dự án sẽ có dạng như sau:

Mở tệp App.js rồi xem phương thức render, trong đó có Thành phần <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>
);
}
Đây là điểm truy cập cho TopAppBar trong ứng dụng.
Mở tệp TopAppBar.js. Đây là một lớp Component React cơ bản có phương thức render:
TopAppBar.js
import React from 'react';
export default class TopAppBar extends React.Component {
render() {
return (
<header>
TOP APP BAR
</header>
);
}
}
3. Thành phần của thành phần
Trong React, phương thức render sẽ xuất HTML của Thành phần. Thành phần Top App Bar sẽ kết xuất thẻ <header /> và bao gồm 2 phần chính:
- Phần tiêu đề và biểu tượng điều hướng
- Mục biểu tượng hành động
Nếu bạn có thắc mắc về các phần tử tạo nên Thanh ứng dụng trên cùng, hãy truy cập vào tài liệu trên GitHub.
Sửa đổi phương thức render() trong TopAppBar.js để có dạng như sau:
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>
);
}
Có hai phần tử section trong HTML này. Phần đầu tiên chứa biểu tượng và tiêu đề điều hướng. Phần thứ hai chứa các biểu tượng thao tác.
Tiếp theo, hãy thêm phương thức 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>
);
}
Nhà phát triển sẽ nhập TopAppBar vào ứng dụng React và truyền biểu tượng thao tác đến phần tử TopAppBar. Bạn có thể xem mã ví dụ khởi chạy một TopAppBar trong App.js.
Thiếu phương thức getMergedStyles được dùng trong phương thức render. Vui lòng thêm phương thức JavaScript sau vào lớp TopAppBar:
getMergedStyles = () => {
const {style} = this.props;
const {style: internalStyle} = this.state;
return Object.assign({}, internalStyle, style);
}
this.classes cũng bị thiếu trong phương thức render, nhưng sẽ được đề cập trong một phần sau. Ngoài phương thức getter bị thiếu, this.classes, vẫn còn các phần của TopAppBar mà bạn cần triển khai trước khi Thanh ứng dụng trên cùng có thể hiển thị chính xác.
Các phần của Thành phần React vẫn còn thiếu trong Thanh ứng dụng trên cùng là:
- Một nền tảng đã khởi chạy
- Các phương thức của bộ chuyển đổi để truyền vào nền tảng
- Ngôn ngữ đánh dấu JSX
- Quản lý biến thể (cố định, ngắn, luôn thu gọn, nổi bật)
Phương pháp tiếp cận
- Triển khai các phương thức Adapter.
- Khởi động Foundation trong
componentDidMount. - Gọi phương thức Foundation.destroy trong
componentWillUnmount. - Thiết lập tính năng quản lý biến thể thông qua một phương thức getter kết hợp các tên lớp thích hợp.
4. Triển khai các phương thức của Bộ chuyển đổi
Thành phần TopAppBar JS không thuộc khuôn khổ triển khai các phương thức Adapter sau đây (được liệt kê chi tiết tại đây):
hasClass()addClass()removeClass()registerNavigationIconInteractionHandler()deregisterNavigationIconInteractionHandler()notifyNavigationIconClicked()setStyle()getTopAppBarHeight()registerScrollHandler()deregisterScrollHandler()registerResizeHandler()deregisterResizeHandler()getViewportScrollY()getTotalActionItems()
Vì React có các sự kiện tổng hợp cũng như các phương pháp hay nhất và mẫu mã khác nhau, nên bạn cần triển khai lại các phương thức Adapter.
Phương thức Getter của bộ chuyển đổi
Trong tệp TopAppBar.js, hãy thêm phương thức JavaScript sau vào 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,
};
}
Các API bộ điều hợp để đăng ký sự kiện cuộn và đổi kích thước được triển khai giống hệt như phiên bản JS không có khung, vì React không có sự kiện tổng hợp nào để cuộn hoặc đổi kích thước và chuyển sang hệ thống sự kiện DOM gốc. getViewPortScrollY cũng cần phải trì hoãn DOM gốc vì đây là một hàm trên đối tượng window, không có trong API của React. Quá trình triển khai bộ chuyển đổi sẽ khác nhau đối với từng khung.
Bạn có thể nhận thấy this.setStyle bị thiếu, được gọi bằng phương thức get adapter. Trong tệp TopAppBar.js, hãy thêm phương thức JavaScript bị thiếu vào lớp TopAppBar:
setStyle = (varName, value) => {
const updatedStyle = Object.assign({}, this.state.style);
updatedStyle[varName] = value;
this.setState({style: updatedStyle});
}
Bạn vừa triển khai Adapter! Xin lưu ý rằng bạn có thể thấy lỗi trong bảng điều khiển tại thời điểm này vì quá trình triển khai đầy đủ chưa hoàn tất. Phần tiếp theo sẽ hướng dẫn bạn cách thêm và xoá các lớp CSS.
5. Triển khai các phương thức Thành phần
Quản lý biến thể và lớp học
React không có API để quản lý các lớp. Để mô phỏng các phương thức thêm/xoá lớp CSS của JavaScript gốc, hãy thêm biến trạng thái classList. Có 3 đoạn mã trong TopAppBar tương tác với các lớp CSS:
- thành phần
<TopAppBar />thông qua thuộc tínhclassName. - Phương thức Adapter thông qua
addClasshoặcremoveClass. - Được mã hoá cứng trong Thành phần
<TopAppBar />React.
Trước tiên, hãy thêm nội dung nhập sau vào đầu TopAppBar.js, bên dưới các nội dung nhập hiện có:
import classnames from 'classnames';
Sau đó, hãy thêm mã sau vào bên trong phần khai báo lớp của Thành phần 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,
});
}
...
}
Nếu bạn truy cập vào http://localhost:8080, các hộp đánh dấu Controls (Chế độ kiểm soát) hiện sẽ bật/tắt tên lớp trong DOM.
Nhiều nhà phát triển có thể sử dụng TopAppBar nhờ mã này. Nhà phát triển có thể tương tác với API TopAppBar mà không phải lo lắng về thông tin triển khai của các lớp CSS.
Giờ thì bạn đã triển khai thành công Trình chuyển đổi. Phần tiếp theo sẽ hướng dẫn bạn cách khởi tạo một Foundation.
Gắn và tháo thành phần
Việc khởi tạo Foundation diễn ra trong phương thức componentDidMount.
Trước tiên, hãy nhập các nền tảng Thanh ứng dụng trên cùng của MDC bằng cách thêm nội dung nhập sau vào sau các nội dung nhập hiện có trong TopAppBar.js:
import {MDCTopAppBarFoundation, MDCFixedTopAppBarFoundation, MDCShortTopAppBarFoundation} from '@material/top-app-bar';
Tiếp theo, hãy thêm đoạn mã JavaScript sau vào lớp 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();
}
...
}
Một phương pháp lập trình hay trong React là xác định propTypes và defaultProps. Thêm nội dung nhập sau vào sau các nội dung nhập hiện có trong TopAppBar.js:
import PropTypes from 'prop-types';
Sau đó, hãy thêm mã sau vào cuối TopAppBar.js (sau lớp Thành phần):
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,
};
Giờ đây, bạn đã triển khai thành công Thành phần React của Thanh ứng dụng trên cùng. Nếu chuyển đến http://localhost:8080, bạn có thể chơi với trang minh hoạ. Trang minh hoạ này sẽ hoạt động giống như trang minh hoạ của MDC Web. Trang minh hoạ sẽ có dạng như sau:

6. Tóm tắt
Trong hướng dẫn này, chúng ta đã tìm hiểu cách bao bọc Foundation của MDC Web để sử dụng trong một ứng dụng React. Có một số thư viện trên Github và npm bao bọc các Thành phần web MDC như mô tả trong phần Tích hợp vào các khung. Bạn nên sử dụng danh sách có tại đây. Danh sách này cũng bao gồm các khung khác ngoài React, chẳng hạn như Angular và Vue.
Hướng dẫn này nêu bật quyết định của chúng tôi về việc chia mã MDC Web thành 3 phần: Foundation (Nền tảng), Adapter (Bộ chuyển đổi) và Component (Thành phần). Cấu trúc này cho phép các thành phần chia sẻ mã chung trong khi hoạt động với tất cả các khung. Cảm ơn bạn đã dùng thử Material Components React. Vui lòng xem thư viện mới của chúng tôi là MDC React. Chúng tôi hy vọng bạn thích lớp học lập trình này!