1. บทนำ
Material Components (MDC) ช่วยให้นักพัฒนาแอปใช้ Material Design ได้ MDC สร้างขึ้นโดยทีมวิศวกรและนักออกแบบ UX จาก Google โดยมีคอมโพเนนต์ UI ที่สวยงามและใช้งานได้จริงหลายสิบรายการ และพร้อมใช้งานสำหรับ Android, iOS, เว็บ และ Flutter ที่ material.io/develop |
MDC Web ได้รับการออกแบบมาให้ผสานรวมกับเฟรมเวิร์กส่วนหน้าได้โดยไม่ขัดต่อหลักการของ Material Design Codelab ต่อไปนี้จะแนะนำวิธีสร้างคอมโพเนนต์ React ซึ่งใช้ MDC Web เป็นรากฐาน หลักการที่เรียนรู้ใน Codelab นี้สามารถนำไปใช้กับเฟรมเวิร์ก JavaScript ใดก็ได้
วิธีสร้าง MDC Web
เลเยอร์ JavaScript ของ MDC Web ประกอบด้วย 3 คลาสต่อคอมโพเนนต์ ได้แก่ Component, Foundation และ Adapter รูปแบบนี้ช่วยให้ MDC Web มีความยืดหยุ่นในการผสานรวมกับเฟรมเวิร์กส่วนหน้า
พื้นฐานมีตรรกะทางธุรกิจที่นำดีไซน์ Material มาใช้ มูลนิธิไม่ได้อ้างอิงองค์ประกอบ HTML ใดๆ ซึ่งช่วยให้เราแยกตรรกะการโต้ตอบกับ HTML ไว้ในอะแดปเตอร์ Foundation มีอะแดปเตอร์
อะแดปเตอร์คืออินเทอร์เฟซ Foundation จะอ้างอิงอินเทอร์เฟซอะแดปเตอร์เพื่อใช้ตรรกะทางธุรกิจของ Material Design คุณสามารถใช้ Adapter ในเฟรมเวิร์กต่างๆ เช่น Angular หรือ React การใช้งานอะแดปเตอร์โต้ตอบกับโครงสร้าง DOM
คอมโพเนนต์มีรากฐาน และบทบาทของรากฐานคือ
- ใช้ Adapter โดยใช้ JavaScript ที่ไม่ใช่เฟรมเวิร์ก และ
- ระบุเมธอดสาธารณะที่เป็นพร็อกซีสำหรับเมธอดใน Foundation
สิ่งที่ MDC Web มีให้
แพ็กเกจทุกรายการใน MDC Web จะมีคอมโพเนนต์ รากฐาน และอะแดปเตอร์ หากต้องการสร้างอินสแตนซ์คอมโพเนนต์ คุณต้องส่งองค์ประกอบรูทไปยังเมธอดคอนสตรัคเตอร์ของคอมโพเนนต์ คอมโพเนนต์ใช้ อะแดปเตอร์ ซึ่งโต้ตอบกับ DOM และองค์ประกอบ HTML จากนั้นคอมโพเนนต์จะสร้างอินสแตนซ์ Foundation ซึ่งจะเรียกใช้เมธอด Adapter
หากต้องการผสานรวม MDC Web เข้ากับเฟรมเวิร์ก คุณต้องสร้างคอมโพเนนต์ของคุณเองในภาษา/ไวยากรณ์ของเฟรมเวิร์กนั้น คอมโพเนนต์ของเฟรมเวิร์กใช้ Adapter ของ MDC Web และใช้ Foundation ของ MDC Web
สิ่งที่คุณจะสร้าง
โค้ดแล็บนี้แสดงวิธีสร้าง Adapter ที่กําหนดเองเพื่อใช้ตรรกะ Foundation เพื่อให้ได้คอมโพเนนต์ React ของ Material Design ซึ่งครอบคลุมหัวข้อขั้นสูงที่พบในการผสานรวมกับเฟรมเวิร์ก React ใช้ใน Codelab นี้เป็นเฟรมเวิร์กตัวอย่าง แต่แนวทางนี้ใช้ได้กับเฟรมเวิร์กอื่นๆ
ในโค้ดแล็บนี้ คุณจะได้สร้างแถบแอปด้านบนและสร้างหน้าสาธิตแถบแอปด้านบนอีกครั้ง เลย์เอาต์ของหน้าสาธิตได้รับการตั้งค่าไว้แล้วเพื่อให้คุณเริ่มทำงานบนแถบแอปด้านบนได้ แถบแอปด้านบนจะมีข้อมูลต่อไปนี้
- ไอคอนการนําทาง
- รายการการทำงาน
- ตัวแปรมี 4 รูปแบบ ได้แก่ สั้น ยุบอยู่เสมอ คงที่ และโดดเด่น
สิ่งที่คุณต้องมี
- Node.js เวอร์ชันล่าสุด (ซึ่งมาพร้อมกับ npm ซึ่งเป็นเครื่องมือจัดการแพ็กเกจ JavaScript)
- โค้ดตัวอย่าง (จะดาวน์โหลดในขั้นตอนถัดไป)
- ความรู้พื้นฐานเกี่ยวกับ HTML, CSS, JavaScript และ React
คุณจะให้คะแนนระดับประสบการณ์ด้านการพัฒนาเว็บเท่าใด
2. ตั้งค่าสภาพแวดล้อมสำหรับนักพัฒนาซอฟต์แวร์
ดาวน์โหลดแอป Codelab เริ่มต้น
แอปเริ่มต้นอยู่ในไดเรกทอรี material-components-web-codelabs-master/mdc-112/starter
...หรือจะโคลนจาก GitHub ก็ได้
หากต้องการโคลนโค้ดแล็บนี้จาก GitHub ให้เรียกใช้คำสั่งต่อไปนี้
git clone https://github.com/material-components/material-components-web-codelabs
cd material-components-web-codelabs/mdc-112/starter
ติดตั้งการอ้างอิงของโปรเจ็กต์
จากไดเรกทอรีเริ่มต้น material-components-web-codelabs/mdc-112/starter
ให้เรียกใช้คำสั่งต่อไปนี้
npm install
คุณจะเห็นกิจกรรมมากมาย และในตอนท้ายเทอร์มินัลควรแสดงการติดตั้งที่สำเร็จ
เรียกใช้แอปเริ่มต้น
ในไดเรกทอรีเดียวกัน ให้เรียกใช้คำสั่งต่อไปนี้
npm start
webpack-dev-server
จะเริ่มต้น ไปที่ http://localhost:8080/ ในเบราว์เซอร์เพื่อดูหน้าเว็บ
สำเร็จ! โค้ดเริ่มต้นสําหรับหน้าสาธิต React ของแถบแอปด้านบนควรทํางานในเบราว์เซอร์ คุณควรเห็นข้อความ 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
ซึ่งเป็นคลาส 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. ใช้เมธอดของอะแดปเตอร์
TopAppBar
คอมโพเนนต์ JS ที่ไม่ใช้เฟรมเวิร์กใช้เมธอด Adapter ต่อไปนี้ (แสดงรายละเอียดไว้ที่นี่)
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 สำหรับจัดการชั้นเรียน หากต้องการเลียนแบบเมธอดเพิ่ม/นําคลาส CSS ของ JavaScript เนทีฟ ให้เพิ่มตัวแปรสถานะ classList
โค้ด 3 รายการใน 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
ได้ นักพัฒนาแอปสามารถโต้ตอบกับ TopAppBar
API ได้โดยไม่ต้องกังวลเกี่ยวกับรายละเอียดการใช้งานคลาส 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 ของแถบแอปด้านบนเรียบร้อยแล้ว หากไปที่ http://localhost:8080 คุณจะเล่นกับหน้าเดโมได้ หน้าสาธิตจะทำงานเหมือนกับหน้าสาธิตของ MRC Web หน้าการสาธิตควรมีลักษณะดังนี้
6. สรุป
ในบทแนะนํานี้ เราจะอธิบายวิธีรวม Foundation ของ MDC Web เพื่อใช้ในแอปพลิเคชัน React มีไลบรารี 2-3 รายการใน Github และ npm ที่รวม MDC Web Components ไว้ด้วยกันตามที่อธิบายไว้ในการผสานรวมกับเฟรมเวิร์ก เราขอแนะนำให้คุณใช้รายการที่ระบุไว้ที่นี่ รายการนี้ยังมีเฟรมเวิร์กอื่นๆ นอกเหนือจาก React เช่น Angular และ Vue
บทแนะนำนี้เน้นที่การตัดสินใจของเราในการแยกโค้ดเว็บ MDC ออกเป็น 3 ส่วน ได้แก่ พื้นฐาน อะแดปเตอร์ และคอมโพเนนต์ สถาปัตยกรรมนี้ช่วยให้คอมโพเนนต์ใช้โค้ดร่วมกันได้ขณะทํางานกับเฟรมเวิร์กทั้งหมด ขอขอบคุณที่ลองใช้ Material Components React และดูไลบรารีใหม่ของเรา MDC React เราหวังว่าคุณจะสนุกกับ Codelab นี้