1. บทนำ
Material Components (MDC) ช่วยให้นักพัฒนานำดีไซน์ Material มาใช้ MDC สร้างโดยทีมวิศวกรและนักออกแบบ UX ที่ Google โดยมีคอมโพเนนต์ UI ที่สวยงามและใช้งานได้หลายสิบอย่างและพร้อมใช้งานสำหรับ Android, iOS, เว็บ และ Flutter.material.io/develop |
MDC Web ได้รับการออกแบบมาเพื่อผสานรวมเข้ากับเฟรมเวิร์กฟรอนท์เอนด์พร้อมกับสนับสนุนหลักการของดีไซน์ Material Codelab ต่อไปนี้จะแนะนำวิธีสร้างคอมโพเนนต์ React ซึ่งใช้ MDC Web เป็นรากฐาน หลักการที่เรียนรู้ใน Codelab นี้สามารถนำไปใช้กับเฟรมเวิร์ก JavaScript ใดก็ได้
การสร้างเว็บ MDC
เลเยอร์ JavaScript ของเว็บ MDC ประกอบด้วย 3 คลาสต่อคอมโพเนนต์ ได้แก่ คอมโพเนนต์ รากฐาน และอะแดปเตอร์ รูปแบบนี้ช่วยให้เว็บ MDC มีความยืดหยุ่นในการผสานรวมกับเฟรมเวิร์กฟรอนท์เอนด์
พื้นฐานมีตรรกะทางธุรกิจที่นำดีไซน์ Material มาใช้ มูลนิธิไม่ได้อ้างอิงองค์ประกอบ HTML ใดๆ ซึ่งจะทำให้เราทำตรรกะการโต้ตอบ HTML ลงในอะแดปเตอร์ได้ Foundation มีอะแดปเตอร์
อะแดปเตอร์เป็นอินเทอร์เฟซ พื้นฐานอ้างอิงอินเทอร์เฟซอะแดปเตอร์เพื่อนำตรรกะทางธุรกิจของดีไซน์ Material มาใช้ คุณสามารถใช้อะแดปเตอร์ในเฟรมเวิร์กที่แตกต่างกัน เช่น Angular หรือ React การใช้งานอะแดปเตอร์โต้ตอบกับโครงสร้าง DOM
คอมโพเนนต์มีรากฐานซึ่งมีหน้าที่ในการ
- ติดตั้งอะแดปเตอร์โดยใช้ JavaScript แบบไม่ใช้เฟรมเวิร์ก และ
- ระบุเมธอดสาธารณะที่พร็อกซีกับเมธอดในพื้นฐาน
สิ่งที่ MDC Web มีให้
แพ็กเกจทั้งหมดใน MDC Web มาพร้อมกับคอมโพเนนต์ พื้นฐาน และอะแดปเตอร์ ในการสร้างอินสแตนซ์ของคอมโพเนนต์ คุณต้องส่งองค์ประกอบรากไปยังเมธอดตัวสร้างของคอมโพเนนต์ คอมโพเนนต์จะใช้อะแดปเตอร์ซึ่งโต้ตอบกับองค์ประกอบ DOM และ HTML จากนั้น Component จะสร้างอินสแตนซ์ Foundation ซึ่งเรียกเมธอด Adapter
หากต้องการผสานรวม MDC Web ไว้ในเฟรมเวิร์ก คุณต้องสร้างคอมโพเนนต์ของคุณเองในภาษา/ไวยากรณ์ของเฟรมเวิร์กนั้น Component ของเฟรมเวิร์กจะใช้อะแดปเตอร์ของ MDC Web และใช้พื้นฐานของ MDC Web
สิ่งที่คุณจะสร้าง
Codelab นี้สาธิตวิธีสร้างอะแดปเตอร์ที่กำหนดเองเพื่อใช้ตรรกะพื้นฐานในการสร้างคอมโพเนนต์ Material Design React ซึ่งครอบคลุมหัวข้อขั้นสูงในหัวข้อการผสานรวมกับเฟรมเวิร์ก มีการใช้ React ใน Codelab นี้เป็นเฟรมเวิร์กตัวอย่าง แต่คุณจะนำวิธีนี้ไปใช้กับเฟรมเวิร์กอื่นๆ ได้ด้วย
ใน Codelab นี้ คุณจะสร้างแถบแอปด้านบนและสร้างหน้าสาธิตแถบแอปด้านบนใหม่ เลย์เอาต์หน้าสาธิตได้รับการตั้งค่าไว้แล้วเพื่อให้คุณเริ่มทํางานบนแถบแอปด้านบนได้ แถบแอปด้านบนจะมีข้อมูลต่อไปนี้
- ไอคอนการนำทาง
- รายการการทำงาน
- มีตัวแปร 4 แบบ ได้แก่ ตัวแปรสั้น ยุบเสมอ คงที่ และโดดเด่น
สิ่งที่คุณต้องมี
- Node.js เวอร์ชันล่าสุด (ซึ่งมาพร้อมกับ npm ซึ่งเป็นเครื่องมือจัดการแพ็กเกจ JavaScript)
- โค้ดตัวอย่าง (จะดาวน์โหลดในขั้นตอนถัดไป)
- ความรู้พื้นฐานเกี่ยวกับ HTML, CSS, JavaScript และ React
คุณจะให้คะแนนประสบการณ์ด้านการพัฒนาเว็บของคุณในระดับใด
2. ตั้งค่าสภาพแวดล้อมในการพัฒนาซอฟต์แวร์
ดาวน์โหลดแอป Codelab เริ่มต้น
แอปเริ่มต้นอยู่ในไดเรกทอรี material-components-web-codelabs-master/mdc-112/starter
...หรือโคลนโมเดลจาก GitHub
หากต้องการโคลน Codelab นี้จาก GitHub ให้เรียกใช้คำสั่งต่อไปนี้
git clone https://github.com/material-components/material-components-web-codelabs
cd material-components-web-codelabs/mdc-112/starter
ติดตั้งทรัพยากร Dependency ของโปรเจ็กต์
จากไดเรกทอรีเริ่มต้น material-components-web-codelabs/mdc-112/starter
ให้เรียกใช้
npm install
คุณจะเห็นกิจกรรมจำนวนมาก และในตอนท้าย เทอร์มินัลควรแสดงการติดตั้งที่สำเร็จ
เรียกใช้แอปเริ่มต้น
โดยให้เรียกใช้สิ่งต่อไปนี้ในไดเรกทอรีเดียวกัน
npm start
webpack-dev-server
จะเริ่มต้น เปิดเบราว์เซอร์และไปที่ http://localhost:8080/ เพื่อดูหน้าเว็บ
สำเร็จ! โค้ดเริ่มต้นสำหรับหน้า Top App Bar React เดโมควรจะทำงานอยู่ในเบราว์เซอร์ของคุณ คุณควรเห็นแผงข้อความ lorem ipsum, ช่อง Controls (ด้านล่างขวา) และแถบแอปด้านบนที่ยังไม่เสร็จสมบูรณ์:
ดูโค้ดและโปรเจ็กต์
หากคุณเปิดตัวแก้ไขโค้ด ไดเรกทอรีโปรเจ็กต์ควรมีลักษณะดังนี้
เปิดไฟล์ 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
ซึ่งเป็นคลาส React Component
เปล่าโดยใช้เมธอด 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 ของคอมโพเนนต์ คอมโพเนนต์ของแถบแอปด้านบนจะแสดงแท็ก <header />
และประกอบด้วยส่วนหลัก 2 ส่วนดังนี้
- ส่วนไอคอนการนำทางและชื่อการนำทาง
- ส่วนไอคอนการทำงาน
หากมีข้อสงสัยเกี่ยวกับองค์ประกอบที่ประกอบเป็นแถบแอปด้านบน โปรดดูเอกสารประกอบใน 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>
);
}
มีองค์ประกอบ 2 ส่วนใน HTML นี้ ป้ายกำกับแรกมีไอคอนการนำทางและชื่อ ส่วนที่ 2 มีไอคอนการดำเนินการ
ถัดไป ให้เพิ่มเมธอด 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
ซึ่งใช้ในเมธอด 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
บางอย่างที่คุณต้องติดตั้งใช้งานก่อนที่แถบแอปด้านบนจะแสดงได้อย่างถูกต้อง
ส่วนต่างๆ ของคอมโพเนนต์ React ที่ยังคงขาดหายไปจากแถบแอปด้านบน ได้แก่
- รากฐานเริ่มต้น
- วิธีการของอะแดปเตอร์ที่จะส่งผ่านไปยังฐานราก
- มาร์กอัป JSX
- การจัดการตัวแปร (คงที่ สั้น ยุบเสมอ โดดเด่น)
วิธีการ
- ใช้เมธอดอะแดปเตอร์
- เริ่มต้นพื้นฐานใน
componentDidMount
- เรียกเมธอด Foundation.destroy ใน
componentWillUnmount
- สร้างการจัดการตัวแปรผ่านเมธอด Getter ที่รวมชื่อคลาสที่เหมาะสมเข้าด้วยกัน
4. ใช้เมธอดของอะแดปเตอร์
คอมโพเนนต์ JS TopAppBar
ที่ไม่ใช่เฟรมเวิร์กจะใช้เมธอดของอะแดปเตอร์ต่อไปนี้ (ดูรายละเอียดได้ที่นี่)
hasClass()
addClass()
removeClass()
registerNavigationIconInteractionHandler()
deregisterNavigationIconInteractionHandler()
notifyNavigationIconClicked()
setStyle()
getTopAppBarHeight()
registerScrollHandler()
deregisterScrollHandler()
registerResizeHandler()
deregisterResizeHandler()
getViewportScrollY()
getTotalActionItems()
เนื่องจาก React มีเหตุการณ์สังเคราะห์ รวมถึงแนวทางปฏิบัติและรูปแบบการเขียนโค้ดที่ดีที่สุดที่แตกต่างกัน จึงต้องนำเมธอดของอะแดปเตอร์มาใช้ใหม่
เมธอดตัวรับอะแดปเตอร์
ในไฟล์ 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 สำหรับจัดการชั้นเรียน หากต้องการเลียนแบบเมธอดเพิ่ม/นำคลาส CSS ของ JavaScript แบบเนทีฟออก ให้เพิ่มตัวแปรสถานะ classList
โค้ดใน TopAppBar
ที่โต้ตอบกับคลาส CSS มี 3 รายการ ได้แก่
- คอมโพเนนต์
<TopAppBar />
ผ่านพร็อพเพอร์ตี้className
- วิธีของอะแดปเตอร์ผ่าน
addClass
หรือremoveClass
- ฮาร์ดโค้ดภายในคอมโพเนนต์รีแอ็กชัน
<TopAppBar />
ขั้นแรก ให้เพิ่มการนำเข้าต่อไปนี้ที่ด้านบนของ 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
ได้ นักพัฒนาแอปจะโต้ตอบกับ TopAppBar
API ได้โดยไม่ต้องกังวลเกี่ยวกับรายละเอียดการใช้งานคลาส CSS
คุณใช้งานอะแดปเตอร์สำเร็จแล้ว ส่วนถัดไปจะแนะนำวิธีการเริ่มต้นรากฐาน
การติดตั้งและยกเลิกการต่อเชื่อมคอมโพเนนต์
การสร้างอินสแตนซ์พื้นฐานจะเกิดขึ้นในเมธอด componentDidMount
ก่อนอื่น ให้นำเข้ารากฐานของ MDC Top App Bar โดยเพิ่มการนำเข้าต่อไปนี้หลังการนำเข้าที่มีอยู่ใน 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,
};
คุณใช้งานคอมโพเนนต์ Top App Bar React สำเร็จแล้ว ถ้าคุณไปที่ http://localhost:8080 คุณจะสามารถเล่นกับหน้าการสาธิตได้ หน้าสาธิตจะทำงานเหมือนกับหน้าสาธิตของ MRC Web หน้าการสาธิตควรมีลักษณะดังนี้
6. สรุป
ในบทแนะนำนี้ เราได้กล่าวถึงวิธีรวมพื้นฐานของ MDC Web เพื่อใช้ในแอปพลิเคชัน React มีไลบรารีบางรายการใน GitHub และ npm ที่รวมคอมโพเนนต์เว็บ MDC ตามที่อธิบายไว้ในการผสานรวมกับเฟรมเวิร์ก เราขอแนะนำให้คุณใช้รายการที่มีอยู่ที่นี่ รายการนี้ยังมีเฟรมเวิร์กอื่นๆ นอกเหนือจาก React เช่น Angular และ Vue
บทแนะนำนี้จะไฮไลต์การตัดสินใจของเราในการแยกโค้ดเว็บ MDC ออกเป็น 3 ส่วน ได้แก่ พื้นฐาน อะแดปเตอร์ และคอมโพเนนต์ สถาปัตยกรรมนี้ช่วยให้คอมโพเนนต์แชร์โค้ดทั่วไปได้ในขณะที่ทำงานกับเฟรมเวิร์กทั้งหมด ขอขอบคุณที่ลองใช้ Material Components React และดูไลบรารีใหม่ของเรา MDC React เราหวังว่าคุณจะชอบ Codelab นี้