分解React組件的幾種進階方法
React 元件魔力無窮,同時彈性超強。我們可以在組件的設計上,玩出很多花樣。但是保證組件的Single responsibility principle: 單一原則非常重要,它可以使得我們的組件更簡單、更方便維護,更重要的是使得組件更加具有復用性。本文主要和大家分享分解React 元件的幾種進階方法,希望能幫助大家。
但是,如何對一個功能複雜且臃腫的 React 元件進行分解,也許並不是一件簡單的事情。本文由淺入深,介紹三個分解 React 元件的方法。
方法一:切割 render() 方法
這是一個最容易想到的方法:當一個元件渲染了許多元素時,就需要嘗試分離這些元素的渲染邏輯。最迅速的方式就是切割 render() 方法為多個 sub-render 方法。
看下面的例子會更直觀:
class Panel extends React.Component { renderHeading() { // ... } renderBody() { // ... } render() { return ( <div> {this.renderHeading()} {this.renderBody()} </div> ); } }
細心的讀者很快就能發現,其實這並沒有分解組件本身,該Panel 組件仍然保持有原先的state, props,以及class 方法。
如何真正做到減少元件複雜度呢?我們需要創建一些子組件。此時,採用最新版 React 支援並推薦的函數式元件/無狀態元件一定會是一個很好的嘗試:
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> ); } }
同之前的方式相比,這個微妙的改進是革命性的。
我們新建了兩個單元組件:PanelHeader 和 PanelBody。這樣帶來了測試的便利,我們可以直接分開測試不同的組件。同時,借助於 React 新的演算法引擎 React Fiber,兩個單元元件在渲染的效率上,樂觀地預期會有較大幅度的提升。
方法二:模版化元件
回到問題的起點,為什麼一個元件會變的臃腫而複雜呢?其一是渲染元素較多且嵌套,另外就是元件內部變化較多,或存在多種 configurations 的情況。
此時,我們便可以將元件改造為模版:父元件類似一個模版,只專注於各種 configurations。
還是要舉例來說,這樣理解起來更加清晰。
例如我們有一個 Comment 元件,這個元件存在多種行為或事件。
同時元件所展現的資訊會根據使用者的身分有所變化:
使用者是否是此comment 的作者;
-
#此comment 是否正確保存;
各種權限不同
-
等等......
都會造成這個元件的不同展示行為。
這時候,與其把所有的邏輯混淆在一起,也許更好的做法是利用React 可以傳遞React element 的特性,我們將React element 進行組件間傳遞,這樣就更加像一個強大的模版:
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> ... ) } }
此時,我們真正的Comment 元件組織為:
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} />; } }
metadata 和actions 其實就是在特定情況下需要渲染的React element。
例如:
如果this.props.publishTime 存在,metadata 就是
; 反之則為Saving...。
如果使用者已經登陸,則需要渲染(即actions值為)
和 ; #如果是作者本身,需要渲染的內容就要加入
。
方法三:高階元件
在實際開發當中,元件常會被其他需求污染。
想想像這樣一個場景:我們想統計頁面中所有連結的點擊資訊。在連結點擊時,發送統計請求,同時這條請求需要包含此頁面 document 的 id 值。
常見的做法是在Document 元件的生命週期函數componentDidMount 和componentWillUnmount 增加程式碼邏輯:
class Document extends React.Component { componentDidMount() { ReactDOM.findDOMNode(this).addEventListener('click', this.onClick); } componentWillUnmount() { ReactDOM.findDOMNode(this).removeEventListener('click', this.onClick); } onClick = (e) => { // Naive check for <a> elements if (e.target.tagName === 'A') { sendAnalytics('link clicked', { // Specific information to be sent documentId: this.props.documentId }); } }; render() { // ... } }
這麼做的幾個問題在於:
#相關元件Document 除了本身的主要邏輯:顯示主頁面之外,多了其他統計邏輯;
#如果Document 元件的生命週期函數中,還有其他邏輯,那麼這個元件就會變的更含糊不合理;
統計邏輯程式碼無法重複使用;
元件重構、維護都會變的更困難。
為了解決這個問題,我們提出了高階元件這個概念: higher-order components (HOCs)。不去晦澀地解釋這個名詞,我們來直接看看使用高階元件如何來重構上面的程式碼:
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) => { // Naive check for <a> elements if (e.target.tagName === 'A') { const data = mapPropsToData ? mapPropsToData(this.props) : {}; sendAnalytics('link clicked', data); } }; render() { // Simply render the WrappedComponent with all props return <WrappedComponent {...this.props} />; } } ... }
要注意的是,withLinkAnalytics 函數並不會去改變WrappedComponent 元件本身,更不會去改變WrappedComponent 元件的行為。而是返回了一個被包裹的新組件。實際用法為:
class Document extends React.Component { render() { // ... } } export default withLinkAnalytics((props) => ({ documentId: props.documentId }), Document);
這樣一來,Document 元件仍只需關心自己該關心的部分,而 withLinkAnalytics 則賦予了復用統計邏輯的能力。
高階元件的存在,完美地展示了 React 天生的複合(compositional)能力,在 React 社群當中,react-redux,styled-components,react-intl 等都普遍採用了這個方式。值得一提的是,recompose 類別庫又利用高階元件,並發揚光大,做到了「腦洞大開」的事。
React 及其周邊社區的崛起,讓函數式程式設計風靡一時,受到追捧。其中關於 decomposing 和 composing 的思想,我認為非常值得學習。同時,對開發設計的一個建議是,一般情況下,不要猶豫將你的組件拆分的更小、更單一,因為這樣能換來強健和復用。
相關推薦:
以上是分解React組件的幾種進階方法的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

ReactRouter使用指南:如何實現前端路由控制隨著單頁應用的流行,前端路由成為了一個不可忽視的重要部分。 ReactRouter作為React生態系統中最受歡迎的路由庫,提供了豐富的功能和易用的API,使得前端路由的實作變得非常簡單和靈活。本文將介紹ReactRouter的使用方法,並提供一些具體的程式碼範例。安裝ReactRouter首先,我們需要

PHP、Vue和React:如何選擇最適合的前端框架?隨著互聯網技術的不斷發展,前端框架在Web開發中起著至關重要的作用。 PHP、Vue和React作為三種代表性的前端框架,每一種都具有其獨特的特徵和優勢。在選擇使用哪種前端框架時,開發人員需要根據專案需求、團隊技能和個人偏好做出明智的決策。本文將透過比較PHP、Vue和React這三種前端框架的特徵和使

Java框架與React框架的整合:步驟:設定後端Java框架。建立專案結構。配置建置工具。建立React應用程式。編寫RESTAPI端點。配置通訊機制。實戰案例(SpringBoot+React):Java程式碼:定義RESTfulAPI控制器。 React程式碼:取得並顯示API回傳的資料。

Vue.js適合中小型項目和快速迭代,React適用於大型複雜應用。 1)Vue.js易於上手,適用於團隊經驗不足或項目規模較小的情況。 2)React的生態系統更豐富,適合有高性能需求和復雜功能需求的項目。

React通過JSX與HTML結合,提升用戶體驗。 1)JSX嵌入HTML,使開發更直觀。 2)虛擬DOM機制優化性能,減少DOM操作。 3)組件化管理UI,提高可維護性。 4)狀態管理和事件處理增強交互性。

react有事件處理函數、useEffect和useCallback、高階元件等等閉包。詳細介紹:1、事件處理函數閉包:在React中,當我們在元件中定義事件處理函數時,函數會形成一個閉包,可以存取元件作用域內的狀態和屬性。這樣可以在事件處理函數中使用元件的狀態和屬性,實現互動邏輯;2、useEffect和useCallback中的閉包等等。

NetflixusesAcustomFrameworkcalled“ Gibbon” BuiltonReact,notReactorVuedIrectly.1)TeamSperience:selectBasedonFamiliarity.2)ProjectComplexity:vueforsimplerprojects:reactforforforproproject,reactforforforcompleplexones.3)cocatizationneedneeds:reactoffipicatizationneedneedneedneedneedneeds:reactoffersizationneedneedneedneedneeds:reactoffersizatization needefersmoreflexibleise.4)

React生態系統包括狀態管理庫(如Redux)、路由庫(如ReactRouter)、UI組件庫(如Material-UI)、測試工具(如Jest)和構建工具(如Webpack)。這些工具協同工作,幫助開發者高效開發和維護應用,提高代碼質量和開發效率。
