React進(jìn)階學(xué)習(xí)之組件的解耦之道
前言
眾所周知,React中的組件非常的靈活可擴(kuò)展,不過隨著業(yè)務(wù)復(fù)雜度的增加和許多外部工具庫的引入,組件往往也會(huì)顯得浮腫,接下來我們就一起來看看常見的幾種,遵循單一職責(zé)原則的,組件分割與解耦的方法,話不多說了,來一起看看詳細(xì)的介紹:
一、分割 render 函數(shù)
當(dāng)一個(gè)組件渲染的內(nèi)容較多時(shí),有一個(gè)快速并且通用的方法是創(chuàng)建sub-render函數(shù)來簡化原來龐大的 render
class Panel extends React.Component { renderHeading() { // ... } renderBody() { // ... } render() { return ( <div> {this.renderHeading()} {this.renderBody()} </div> ); } }
為了再次簡化sub-render函數(shù),我們還可以采用Functional Components寫法,這種方式生成了更小的處理單元,且更有利于測試
const PanelHeader = (props) => ( // ... ); const PanelBody = (props) => ( // ... ); class Panel extends React.Component { render() { return ( <div> // Nice and explicit about which props are used <PanelHeader title={this.props.title}/> <PanelBody content={this.props.content}/> </div> ); } }
二、用 props 傳遞元素
如果一個(gè)組件的狀態(tài)或配置較多,我們可以運(yùn)用props傳遞元素而不僅是數(shù)據(jù),比如再聲明一個(gè)組件,使其中的父組件只專注于配置
class CommentTemplate extends React.Component { static propTypes = { // Declare slots as type node metadata: PropTypes.node, actions: PropTypes.node, }; render() { return ( <div> <CommentHeading> <Avatar user={...}/> // Slot for metadata <span>{this.props.metadata}</span> </CommentHeading> <CommentBody/> <CommentFooter> <Timestamp time={...}/> // Slot for actions <span>{this.props.actions}</span> </CommentFooter> </div> ); } }
父組件
class Comment extends React.Component { render() { const metadata = this.props.publishTime ? <PublishTime time={this.props.publishTime} /> : <span>Saving...</span>; const actions = []; if (this.props.isSignedIn) { actions.push(<LikeAction />); actions.push(<ReplyAction />); } if (this.props.isAuthor) { actions.push(<DeleteAction />); } return <CommentTemplate metadata={metadata} actions={actions} />; } }
三、使用高階組件
實(shí)現(xiàn)點(diǎn)擊某組件的超鏈接,發(fā)送該組件的 ID,我們大多的解決方法可能如下
class Document extends React.Component { componentDidMount() { ReactDOM.findDOMNode(this).addEventListener('click', this.onClick); } componentWillUnmount() { ReactDOM.findDOMNode(this).removeEventListener('click', this.onClick); } onClick = (e) => { if (e.target.tagName === 'A') { // Naive check for <a> elements sendAnalytics('link clicked', { documentId: this.props.documentId // Specific information to be sent }); } }; render() { // ... } }
然而它卻存在代碼不能復(fù)用,組件重構(gòu)困難等問題
我們可以使用高階組件來解決這些問題,顧名思義,高階組件就是一個(gè)函數(shù),傳給它一個(gè)組件,它返回一個(gè)新的組件
function withLinkAnalytics(mapPropsToData, WrappedComponent) { class LinkAnalyticsWrapper extends React.Component { componentDidMount() { ReactDOM.findDOMNode(this).addEventListener('click', this.onClick); } componentWillUnmount() { ReactDOM.findDOMNode(this).removeEventListener('click', this.onClick); } onClick = (e) => { if (e.target.tagName === 'A') { // Naive check for <a> elements const data = mapPropsToData ? mapPropsToData(this.props) : {}; sendAnalytics('link clicked', data); } }; render() { // Simply render the WrappedComponent with all props return <WrappedComponent {...this.props} />; } } return LinkAnalyticsWrapper; }
簡化代碼如下
class Document extends React.Component { render() { // ... } } export default withLinkAnalytics((props) => ({ documentId: props.documentId }), Document);
總結(jié)
以上 3 個(gè) React 組件的解耦重構(gòu)方法都可以直接拿來運(yùn)用,最開始可能會(huì)覺得有點(diǎn)棘手,但是沒關(guān)系,只要堅(jiān)持下來,你就會(huì)寫出更強(qiáng)壯和可復(fù)用的代碼。
好了,以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作能帶來一定的幫助,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。
相關(guān)文章
redux功能強(qiáng)大的Middleware中間件使用學(xué)習(xí)
這篇文章主要為大家介紹了redux功能強(qiáng)大的Middleware中間件使用學(xué)習(xí),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09基于React-Dropzone開發(fā)上傳組件功能(實(shí)例演示)
這篇文章主要介紹了基于React-Dropzone開發(fā)上傳組件,主要講述的是在React-Flask框架上開發(fā)上傳組件的技巧,需要的朋友可以參考下2021-08-08深入理解React Native核心原理(React Native的橋接(Bridge)
這篇文章主要介紹了深入理解React Native核心原理(React Native的橋接(Bridge),本文重點(diǎn)給大家介紹React Native的基礎(chǔ)知識及實(shí)現(xiàn)原理,需要的朋友可以參考下2021-04-04react中value與defaultValue的區(qū)別及說明
這篇文章主要介紹了react中value與defaultValue的區(qū)別及說明,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-05-05前端開發(fā)使用Ant Design項(xiàng)目評價(jià)
這篇文章主要為大家介紹了前端開發(fā)使用Ant Design項(xiàng)目評價(jià),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08漸進(jìn)式源碼解析React更新流程驅(qū)動(dòng)
這篇文章主要為大家介紹了漸進(jìn)式源碼解析React更新流程驅(qū)動(dòng)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-04-04React項(xiàng)目中報(bào)錯(cuò):Parsing error: The keyword &a
ESLint 默認(rèn)使用的是 ES5 語法,如果你想使用 ES6 或者更新的語法,你需要在 ESLint 的配置文件如:.eslintrc.js等中設(shè)置 parserOptions,這篇文章主要介紹了React項(xiàng)目中報(bào)錯(cuò):Parsing error: The keyword 'import' is reservedeslint的問題及解決方法,需要的朋友可以參考下2023-12-12Remix后臺(tái)開發(fā)之remix-antd-admin配置過程
這篇文章主要為大家介紹了Remix后臺(tái)開發(fā)之remix-antd-admin配置過程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-04-04