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 bất kỳ khung giao diện người dùng nào, đồng thời duy trì các nguyên tắc của Material Design. Lớp học lập trình sau đây sẽ 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 bất kỳ khung JavaScript nào.
Cách xây dựng MDC Web
Lớp JavaScript của MDC Web bao gồm 3 lớp cho mỗi thành phần: Thành phần, Nền tảng và Bộ chuyển đổi. Mẫu này giúp MDC Web linh hoạt tích hợp với các khung giao diện người dùng.
Foundation 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. Điều này cho phép chúng ta trừu tượng hoá logic tương tác HTML vào Bộ chuyển đổi. Foundation có một Adapter (Bộ chuyển đổi).
Bộ chuyển đổi là một giao diện. Giao diện Trình chuyển đổi được Foundation tham chiếu để triển khai logic nghiệp vụ của Material Design. Bạn có thể triển khai Trình chuyển đổi trong nhiều khung như Angular hoặc React. Việc triển khai Bộ chuyển đổi tương tác với cấu trúc DOM.
Thành phần có một Foundation (Nền tảng) và vai trò của thành phần này là
- Triển khai Trình chuyển đổi, sử dụng JavaScript không phải khung và
- Cung cấp các phương thức công khai làm proxy cho các phương thức trong Foundation.
Những gì MDC Web cung cấp
Mỗi gói trong MDC Web đều có một Thành phần, Nền tảng và Bộ chuyển đổi. Để tạo thực thể cho một Thành phần, bạn phải truyền phần tử gốc đến phương thức hàm khởi tạo của Thành phần đó. Thành phần triển khai một Trình chuyển đổi, tương tác với các phần tử DOM và HTML. Sau đó, Component (Thành phần) sẽ tạo thực thể cho Foundation. Nền tảng này sẽ gọi 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ữ/ngữ pháp của khung đó. Thành phần của khung này triển khai Trình chuyển đổi của MDC Web và sử dụng Nền tảng 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 Trình chuyển đổi tuỳ chỉnh để sử dụng logic Foundation nhằm đạt được Thành phần React Material Design. Bài viết này đề cập đến các chủ đề nâng cao trong phần Tích hợp vào khung. React được dùng trong lớp học lập trình này làm khung mẫu, nhưng cũng có thể áp dụng 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ạ 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 đi theo chỉ dẫn
- Mục hành động
- Có 4 biến thể có sẵn: biến thể Ngắn, luôn thu gọn, cố định và nổi bật
Những gì bạn cần:
- 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ề mức độ kinh nghiệm của mình trong việ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
Ứng dụng khởi động 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 phần phụ thuộc dự án
Từ thư mục khởi động 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ẽ hiển thị thông báo cài đặt thành công:
Chạy ứng dụng ban đầu
Trong cùng thư mục, hãy chạy:
npm start
webpack-dev-server
sẽ bắt đầu. Trỏ trình duyệt của bạn đến http://localhost:8080/ để xem trang.
Thành công! Mã khởi đầu cho trang Bản minh hoạ phản ứng của thanh ứng dụng trên cùng phải đang 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 (Chế độ đ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 tất:
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
và 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
là một lớp React Component
đơn thuần bằng 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. Cấu trúc của thành phần
Trong React, phương thức render
sẽ xuất ra HTML của Thành phần. Thành phần Thanh ứng dụng trên cùng sẽ hiển thị 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 thành phần 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
thành 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. Nội dung đầu tiên chứa biểu tượng điều hướng và tiêu đề. Thẻ thứ hai chứa các biểu tượng hành động.
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 hành động đến phần tử TopAppBar
. Bạn có thể xem mã ví dụ khởi chạy 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 đây 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 phần sau. Ngoài phương thức getter bị thiếu, this.classes
, bạn vẫn cần triển khai một số phần của TopAppBar
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 chuyển đổi để truyền vào nền tảng
- Mã đá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 Trình chuyển đổi.
- Khởi chạy Foundation trong
componentDidMount
. - Gọi phương thức Foundation.destroy trong
componentWillUnmount
. - Thiết lập cách 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 phù hợp.
4. Triển khai các phương thức của Trình chuyển đổi
Thành phần TopAppBar
JS không theo khung triển khai các phương thức Bộ chuyển đổi 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 và nhiều phương pháp và mẫu lập trình hay nhất, nên bạn cần triển khai lại các phương thức Trình chuyển đổi.
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 đây 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ộ chuyển đổi để đă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à sẽ 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. Cách triển khai bộ chuyển đổi sẽ khác nhau tuỳ theo từng khung.
Bạn có thể nhận thấy this.setStyle
bị thiếu, phương thức này được gọi bởi 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 Bộ chuyển đổi! Xin lưu ý rằng tại thời điểm này, bạn có thể thấy lỗi trong bảng điều khiển 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
React không có API để quản lý 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ó ba đ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 Trình chuyển đổi thông qua
addClass
hoặcremoveClass
. - Được mã hoá cứng trong Thành phần React
<TopAppBar />
.
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 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 chuyển đến http://localhost:8080, các hộp đánh dấu Controls (Chế độ điều khiển) hiện sẽ bật/tắt tên lớp từ DOM.
Mã này giúp nhiều nhà phát triển có thể sử dụng TopAppBar
. Nhà phát triển có thể tương tác với API TopAppBar
mà không phải lo lắng về các chi tiết 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 tạo bản sao Foundation.
Gắn và tháo thành phần
Quá trình tạo thực thể nền 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 lệnh nhập sau đây sau các lệnh nhập hiện có trong TopAppBar.js
:
import {MDCTopAppBarFoundation, MDCFixedTopAppBarFoundation, MDCShortTopAppBarFoundation} from '@material/top-app-bar';
Tiếp theo, hãy thêm 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 cho React là xác định propTypes và defaultProps. Thêm lệnh nhập sau đây sau các lệnh 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 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,
};
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ạ 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 đã đề cập đến cách gói Foundation của MDC Web để sử dụng trong ứng dụng React. Có một số thư viện trên GitHub và npm bao bọc Thành phần web MDC như mô tả trong phần Tích hợp vào khung. Bạn nên sử dụng danh sách 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ã Web MDC thành 3 phần, đó là 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 làm việc với tất cả các khung. Cảm ơn bạn đã dùng thử Material Components React. Vui lòng tham khảo thư viện mới của chúng tôi MDC React. Chúng tôi hy vọng bạn đã thích lớp học lập trình này!