目錄
方法一:切割 render() 方法
方法二:模版化元件
方法三:高階元件
首頁 web前端 js教程 分解React組件的幾種進階方法

分解React組件的幾種進階方法

Feb 09, 2018 pm 04:40 PM
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元件生命週期實例分析

#建構React元件最全方法

store優化React元件的方法詳解

以上是分解React組件的幾種進階方法的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

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

熱門文章

<🎜>:泡泡膠模擬器無窮大 - 如何獲取和使用皇家鑰匙
4 週前 By 尊渡假赌尊渡假赌尊渡假赌
北端:融合系統,解釋
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌
Mandragora:巫婆樹的耳語 - 如何解鎖抓鉤
4 週前 By 尊渡假赌尊渡假赌尊渡假赌
<🎜>掩蓋:探險33-如何獲得完美的色度催化劑
2 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

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

熱門話題

Java教學
1677
14
CakePHP 教程
1430
52
Laravel 教程
1333
25
PHP教程
1278
29
C# 教程
1257
24
React Router使用指南:如何實現前端路由控制 React Router使用指南:如何實現前端路由控制 Sep 29, 2023 pm 05:45 PM

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

PHP、Vue和React:如何選擇最適合的前端框架? PHP、Vue和React:如何選擇最適合的前端框架? Mar 15, 2024 pm 05:48 PM

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

Java框架與前端React框架的整合 Java框架與前端React框架的整合 Jun 01, 2024 pm 03:16 PM

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

vue.js vs.反應:特定於項目的考慮因素 vue.js vs.反應:特定於項目的考慮因素 Apr 09, 2025 am 12:01 AM

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

React在HTML中的作用:增強用戶體驗 React在HTML中的作用:增強用戶體驗 Apr 09, 2025 am 12:11 AM

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

react有哪些閉包 react有哪些閉包 Oct 27, 2023 pm 03:11 PM

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

React與Vue:Netflix使用哪個框架? React與Vue:Netflix使用哪個框架? Apr 14, 2025 am 12:19 AM

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

React的生態系統:庫,工具和最佳實踐 React的生態系統:庫,工具和最佳實踐 Apr 18, 2025 am 12:23 AM

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

See all articles