1. מבוא
Material Components (MDC) עוזרים למפתחים להטמיע את Material Design. MDC נוצר על ידי צוות של מהנדסים ומעצבי חוויית המשתמש ב-Google, שכולל עשרות רכיבים יפים ופונקציונליים של ממשק המשתמש. זמין ל-Android, ל-iOS, לאינטרנט ול-Flutter.material.io/develop |
MDC Web תוכנן כך שאפשר לשלב אותו בכל מסגרת חזית, תוך שמירה על עקרונות העיצוב של Material Design. בקודלאב הבא תלמדו איך ליצור רכיב React שמשתמש ב-MDC Web כבסיס. אפשר להחיל את העקרונות שלמדתם בקודלאב הזה על כל מסגרת של JavaScript.
איך נוצר MDC Web
שכבת JavaScript של MDC Web מורכבת משלוש כיתות לכל רכיב: Component, Foundation ו-Adapter. התבנית הזו מעניקה ל-MDC Web גמישות לשילוב עם מסגרות חזית.
הבסיס מכיל את הלוגיקה העסקית שמטמיעה את העיצוב החדשני. ב-Foundation אין הפניה לרכיבי HTML. כך אנחנו יכולים להעביר את הלוגיקה של אינטראקציית ה-HTML למתאם. ל-Foundation יש מתאם.
המתאם הוא ממשק. הבסיס מפנה לממשק המתאם כדי להטמיע לוגיקה עסקית של Material Design. אפשר להטמיע את המתאם במסגרות שונות, כמו Angular או React. הטמעה של מתאם יוצרת אינטראקציה עם מבנה ה-DOM.
לרכיב יש בסיס, והתפקיד שלו הוא
- מטמיעים את המתאם באמצעות JavaScript ללא מסגרת, וגם
- לספק שיטות ציבוריות שמעבירות שיטות ל-Foundation.
מה MDC Web מספק
כל חבילת MDC Web כוללת רכיב, בסיס ומתאם. כדי ליצור רכיב, צריך להעביר את הרכיב הבסיסי (root) ל-method של ה-constructor של הרכיב. הרכיב מיישם מתאם, שמקיים אינטראקציה עם רכיבי ה-DOM וה-HTML. לאחר מכן הרכיב מייצר את ה-Foundation, שקוראת ל-methods של מתאם.
כדי לשלב את MDC Web במסגרת, צריך ליצור רכיב משלכם בשפה או בסנטקס של המסגרת הזו. הרכיב Component של המסגרת מטמיע את Adapter של MDC Web ומשתמש ב-Foundation של MDC Web.
מה תפַתחו
בשיעור הזה תלמדו איך ליצור מתאם מותאם אישית כדי להשתמש בלוגיקה של Foundation כדי ליצור רכיב React של Material Design. הוא מכיל את הנושאים המתקדמים שמפורטים בקטע שילוב במסגרות. ב-codelab הזה נעשה שימוש ב-React כמסגרת לדוגמה, אבל אפשר ליישם את הגישה הזו בכל מסגרת אחרת.
בקודלאב הזה תלמדו ליצור את סרגל האפליקציות העליון, וליצור מחדש את דף הדגמה של סרגל האפליקציות העליון. הפריסה של דף ההדגמה כבר מוגדרת, כך שתוכלו להתחיל לעבוד על סרגל האפליקציות העליון. סרגל האפליקציות העליון יכלול:
- סמל הניווט
- פעולות לביצוע
- יש 4 וריאנטים זמינים: קצר, תמיד מכווץ, קבוע ובולט
מה צריך:
- גרסה עדכנית של Node.js (שכוללת את npm, מנהל חבילות של JavaScript)
- הקוד לדוגמה (להורדה בשלב הבא)
- ידע בסיסי ב-HTML, CSS, JavaScript ו-React
מה מידת הניסיון שלך בפיתוח אינטרנט?
2. הגדרה של סביבת הפיתוח
הורדת האפליקציה לתחילת הדרך ב-Codelab
אפליקציית ההתחלה נמצאת בספרייה material-components-web-codelabs-master/mdc-112/starter
.
...או לשכפל אותו מ-GitHub
כדי להעתיק (clone) את סדנת הקוד הזו מ-GitHub, מריצים את הפקודות הבאות:
git clone https://github.com/material-components/material-components-web-codelabs
cd material-components-web-codelabs/mdc-112/starter
התקנת יחסי התלות בפרויקט
בספריית ה-starter material-components-web-codelabs/mdc-112/starter
, מריצים את הפקודה:
npm install
תראו הרבה פעילות, ובסוף אמורה להופיע הודעה על התקנה מוצלחת במסוף:
הפעלת האפליקציה למתחילים
באותה ספרייה, מריצים את הפקודה:
npm start
ה-webpack-dev-server
יתחיל לפעול. כדי להציג את הדף, מזינים בדפדפן את הכתובת http://localhost:8080/.
הצלחת! הקוד הראשוני של הדף Top App Bar React Demo אמור לפעול בדפדפן. אמור להופיע קיר של טקסט lorem ipsum, תיבה של אמצעי בקרה (בפינה השמאלית התחתונה) וסרגל האפליקציות העליון שעדיין לא הושלם:
עיון בקוד ובפרויקט
אם פותחים את עורך הקוד, ספריית הפרויקט אמורה להיראות בערך כך:
פותחים את הקובץ App.js
ובודקים את השיטה render
, שכוללת את הרכיב <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>
);
}
זוהי נקודת הכניסה של TopAppBar
באפליקציה.
פותחים את הקובץ TopAppBar.js
, שהוא כיתה Component
רגילה של React עם שיטת render
:
TopAppBar.js
import React from 'react';
export default class TopAppBar extends React.Component {
render() {
return (
<header>
TOP APP BAR
</header>
);
}
}
3. הרכב הרכיב
ב-React, השיטה render
מפיקה את ה-HTML של הרכיב. רכיב Top App Bar ייצור תג <header />
ויורכב משני חלקים עיקריים:
- סמל הניווט והקטע של הכותרת
- קטע של סמלי פעולות
אם יש לכם שאלות לגבי הרכיבים שמרכיבים את סרגל האפליקציות העליון, תוכלו לעיין במאמרי העזרה ב-GitHub.
משנים את השיטה render()
ב-TopAppBar.js
כך שתהיה דומה לזו:
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>
);
}
יש שני רכיבי קטע בקוד ה-HTML הזה. השורה הראשונה מכילה סמל ניווט וכותרת. השני מכיל סמלי פעולה.
בשלב הבא מוסיפים את השיטה 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>
);
}
מפתחים מייבאים את TopAppBar
לאפליקציית React שלהם ומעבירים את סמלי הפעולות לרכיב TopAppBar
. אפשר לראות קוד לדוגמה לאינטוליזציה של TopAppBar
ב-App.js
.
חסרה השיטה getMergedStyles
, שנעשה בה שימוש ב-method render
. עליך להוסיף את שיטת JavaScript הבאה לכיתה TopAppBar
:
getMergedStyles = () => {
const {style} = this.props;
const {style: internalStyle} = this.state;
return Object.assign({}, internalStyle, style);
}
גם השדה this.classes
חסר בשיטה render
, אבל הוא ייבדק בקטע מאוחר יותר. בנוסף לשיטת ה-getter this.classes
שחסרה, עדיין יש חלקים ב-TopAppBar
שצריך להטמיע כדי שאפשר יהיה להציג את Top App Bar בצורה נכונה.
החלקים של רכיב React שעדיין חסרים בסרגל העליון של האפליקציה הם:
- בסיס שהופעל
- שיטות של מתאמים להעברה ל-Foundation
- תגי עיצוב של JSX
- ניהול וריאנטים (קבוע, קצר, תמיד מכווץ, בולט)
הגישה
- מטמיעים את השיטות של Adapter.
- מפעילים את הבסיס ב-
componentDidMount
. - קוראים ל-method Foundation.destroy ב-
componentWillUnmount
. - מגדירים ניהול של וריאנטים באמצעות שיטת getter שמשלבת שמות של כיתות מתאימות.
4. הטמעת שיטות של מתאם
הרכיב TopAppBar
של JS ללא מסגרת מיישם את השיטות הבאות של מתאם (רשימת השיטות מפורטת כאן):
hasClass()
addClass()
removeClass()
registerNavigationIconInteractionHandler()
deregisterNavigationIconInteractionHandler()
notifyNavigationIconClicked()
setStyle()
getTopAppBarHeight()
registerScrollHandler()
deregisterScrollHandler()
registerResizeHandler()
deregisterResizeHandler()
getViewportScrollY()
getTotalActionItems()
מכיוון של-React יש אירועים סינתטיים ושיטות ותבניות שונות של קוד מומלץ, צריך להטמיע מחדש את השיטות של Adapter.
שיטת Getter של מתאם
בקובץ TopAppBar.js
, מוסיפים את שיטת ה-JavaScript הבאה ל-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 של המתאם לרישום אירועי גלילה ושינוי גודל מיושמים באופן זהה לגרסה של JS ללא מסגרת, כי ל-React אין אירוע סינתטי לגלילה או לשינוי גודל, והוא מסתמך על מערכת האירועים המקורית של DOM. getViewPortScrollY
צריך גם להעביר את הבקשה ל-DOM המקורי כי זו פונקציה באובייקט window
, שלא נמצא ב-API של React. ההטמעות של המתאם יהיו שונות בכל מסגרת.
יכול להיות שחסרים תווים this.setStyle
, שמופעלת על ידי השיטה get adapter
. בקובץ TopAppBar.js
, מוסיפים את שיטת JavaScript החסרה לכיתה TopAppBar
:
setStyle = (varName, value) => {
const updatedStyle = Object.assign({}, this.state.style);
updatedStyle[varName] = value;
this.setState({style: updatedStyle});
}
הטמעתם את המתאם! שימו לב שייתכן שיופיעו שגיאות במסוף בשלב הזה כי ההטמעה המלאה עדיין לא הושלמה. בקטע הבא מוסבר איך להוסיף ולהסיר מחלקות CSS.
5. הטמעת שיטות של רכיבים
ניהול וריאנטים וכיתות
ל-React אין ממשק API לניהול כיתות. כדי לחקות את שיטות ההוספה/הסרה של JavaScript ליצירת סוגים של CSS, מוסיפים את משתנה המצב classList
. יש שלושה קטעי קוד ב-TopAppBar
שמקיימים אינטראקציה עם כיתות CSS:
- רכיב
<TopAppBar />
דרך המאפייןclassName
. - השיטה Adapter דרך
addClass
אוremoveClass
. - מופיע בתוך הקוד ברכיב
<TopAppBar />
React.
קודם כול, מוסיפים את הייבוא הבא בחלק העליון של TopAppBar.js
, מתחת לייבוא הקיים:
import classnames from 'classnames';
לאחר מכן מוסיפים את הקוד הבא בהצהרת הכיתה של הרכיב 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,
});
}
...
}
אם עוברים אל http://localhost:8080, התיבות הסימון של אמצעי הבקרה אמורות להפעיל או להשבית את שמות הכיתות מ-DOM.
הקוד הזה מאפשר למפתחים רבים להשתמש ב-TopAppBar
. מפתחים יכולים לקיים אינטראקציה עם ה-API של TopAppBar
בלי לדאוג לפרטים של ההטמעה של כיתות CSS.
הטמעתם בהצלחה את המתאם. בקטע הבא נסביר איך יוצרים מופע של Foundation.
התקנה והסרה של הרכיב
יצירת המופעים של Foundation מתבצעת בשיטה componentDidMount
.
קודם כול, מייבאים את היסודות של סרגל האפליקציות העליון של MDC על ידי הוספת הייבוא הבא אחרי הייבוא הקיים בקובץ TopAppBar.js
:
import {MDCTopAppBarFoundation, MDCFixedTopAppBarFoundation, MDCShortTopAppBarFoundation} from '@material/top-app-bar';
בשלב הבא, מוסיפים את קוד ה-JavaScript הבא למחלקה 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();
}
...
}
שיטה טובה לתכנות ב-React היא להגדיר את propTypes ואת defaultProps. אחרי פעולות הייבוא הקיימות ב-TopAppBar.js, צריך להוסיף את הייבוא הבא:
import PropTypes from 'prop-types';
לאחר מכן מוסיפים את הקוד הבא לתחתית של TopAppBar.js
(אחרי מחלקת הרכיבים):
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,
};
סיימתם להטמיע את רכיב React של Top App Bar. אם עוברים אל http://localhost:8080, אפשר לשחק עם דף הדמו. דף הדגמה יפעל כמו דף הדגמה של MDC Web. דף הדגמה אמור להיראות כך:
6. סיכום
במדריך הזה הראינו איך לעטוף את הבסיס של MDC Web לשימוש באפליקציית React. יש כמה ספריות ב-GitHub וב-npm שמארזות את MDC Web Components, כפי שמתואר בקטע שילוב ב-Frameworks. מומלץ להשתמש ברשימה שמופיעה כאן. הרשימה הזו כוללת גם מסגרות אחרות מלבד React, כמו Angular ו-Vue.
במדריך הזה נסביר על ההחלטה שלנו לפצל את הקוד של MDC Web ל-3 חלקים: Foundation, Adapter ו-Component. הארכיטקטורה הזו מאפשרת לרכיבים לשתף קוד משותף תוך כדי עבודה עם כל המסגרות. תודה שניסית את Material Components React. מומלץ לבדוק את הספרייה החדשה שלנו, MDC React. אנחנו מקווים שנהנית מה-Codelab הזה.