• <fieldset id="8imwq"><menu id="8imwq"></menu></fieldset>
  • <bdo id="8imwq"><input id="8imwq"></input></bdo>
    最新文章專題視頻專題問答1問答10問答100問答1000問答2000關(guān)鍵字專題1關(guān)鍵字專題50關(guān)鍵字專題500關(guān)鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關(guān)鍵字專題關(guān)鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
    問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
    當(dāng)前位置: 首頁 - 科技 - 知識(shí)百科 - 正文

    分解React組件的幾種進(jìn)階方法

    來源:懂視網(wǎng) 責(zé)編:小采 時(shí)間:2020-11-27 20:03:31
    文檔

    分解React組件的幾種進(jìn)階方法

    分解React組件的幾種進(jìn)階方法:React 組件魔力無窮,同時(shí)靈活性超強(qiáng)。我們可以在組件的設(shè)計(jì)上,玩轉(zhuǎn)出很多花樣。但是保證組件的Single responsibility principle: 單一原則非常重要,它可以使得我們的組件更簡(jiǎn)單、更方便維護(hù),更重要的是使得組件更加具有復(fù)用性。本文主要和大家分享分解R
    推薦度:
    導(dǎo)讀分解React組件的幾種進(jìn)階方法:React 組件魔力無窮,同時(shí)靈活性超強(qiáng)。我們可以在組件的設(shè)計(jì)上,玩轉(zhuǎn)出很多花樣。但是保證組件的Single responsibility principle: 單一原則非常重要,它可以使得我們的組件更簡(jiǎn)單、更方便維護(hù),更重要的是使得組件更加具有復(fù)用性。本文主要和大家分享分解R

    React 組件魔力無窮,同時(shí)靈活性超強(qiáng)。我們可以在組件的設(shè)計(jì)上,玩轉(zhuǎn)出很多花樣。但是保證組件的Single responsibility principle: 單一原則非常重要,它可以使得我們的組件更簡(jiǎn)單、更方便維護(hù),更重要的是使得組件更加具有復(fù)用性。本文主要和大家分享分解React 組件的幾種進(jìn)階方法,希望能幫助到大家。

    但是,如何對(duì)一個(gè)功能復(fù)雜且臃腫的 React 組件進(jìn)行分解,也許并不是一件簡(jiǎn)單的事情。本文由淺入深,介紹三個(gè)分解 React 組件的方法。

    方法一:切割 render() 方法

    這是一個(gè)最容易想到的方法:當(dāng)一個(gè)組件渲染了很多元素時(shí),就需要嘗試分離這些元素的渲染邏輯。最迅速的方式就是切割 render() 方法為多個(gè) sub-render 方法。

    看下面的例子會(huì)更加直觀:

    class Panel extends React.Component {
     renderHeading() { // ...
     }
    
     renderBody() { // ...
     }
    
     render() { return (
     <div>
     {this.renderHeading()}
     {this.renderBody()}
     </div>
     );
     }
    }

    細(xì)心的讀者很快就能發(fā)現(xiàn),其實(shí)這并沒有分解組件本身,該 Panel 組件仍然保持有原先的 state, props, 以及 class 方法。

    如何真正地做到減少組件復(fù)雜度呢?我們需要?jiǎng)?chuàng)建一些子組件。此時(shí),采用最新版 React 支持并推薦的函數(shù)式組件/無狀態(tài)組件一定會(huì)是一個(gè)很好的嘗試:

    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>
     );
     }
    }

    同之前的方式相比,這個(gè)微妙的改進(jìn)是革命性的。

    我們新建了兩個(gè)單元組件:PanelHeader 和 PanelBody。這樣帶來了測(cè)試的便利,我們可以直接分離測(cè)試不同的組件。同時(shí),借助于 React 新的算法引擎 React Fiber,兩個(gè)單元組件在渲染的效率上,樂觀地預(yù)計(jì)會(huì)有較大幅度的提升。

    方法二:模版化組件

    回到問題的起點(diǎn),為什么一個(gè)組件會(huì)變的臃腫而復(fù)雜呢?其一是渲染元素較多且嵌套,另外就是組件內(nèi)部變化較多,或者存在多種 configurations 的情況。

    此時(shí),我們便可以將組件改造為模版:父組件類似一個(gè)模版,只專注于各種 configurations。

    還是要舉例來說,這樣理解起來更加清晰。

    比如我們有一個(gè) Comment 組件,這個(gè)組件存在多種行為或事件。

    同時(shí)組件所展現(xiàn)的信息根據(jù)用戶的身份不同而有所變化:

  • 用戶是否是此 comment 的作者;

  • 此 comment 是否被正確保存;

  • 各種權(quán)限不同

  • 等等......

  • 都會(huì)引起這個(gè)組件的不同展示行為。

    這時(shí)候,與其把所有的邏輯混淆在一起,也許更好的做法是利用 React 可以傳遞 React element 的特性,我們將 React element 進(jìn)行組件間傳遞,這樣就更加像一個(gè)強(qiáng)大的模版:

    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>
     ...
     )
     }
    }

    此時(shí),我們真正的 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 其實(shí)就是在特定情況下需要渲染的 React element。

    比如:

  • 如果 this.props.publishTime 存在,metadata 就是 <PublishTime time={this.props.publishTime} />;

  • 反之則為 <span>Saving...</span>。

  • 如果用戶已經(jīng)登陸,則需要渲染(即actions值為) <LikeAction /> 和 <ReplyAction />;

  • 如果是作者本身,需要渲染的內(nèi)容就要加入 <DeleteAction />。

  • 方法三:高階組件

    在實(shí)際開發(fā)當(dāng)中,組件經(jīng)常會(huì)被其他需求所污染。

    想象這樣一個(gè)場(chǎng)景:我們想統(tǒng)計(jì)頁面中所有鏈接的點(diǎn)擊信息。在鏈接點(diǎn)擊時(shí),發(fā)送統(tǒng)計(jì)請(qǐng)求,同時(shí)這條請(qǐng)求需要包含此頁面 document 的 id 值。

    常見的做法是在 Document 組件的生命周期函數(shù) 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() { // ...
     }
    }

    這么做的幾個(gè)問題在于:

  • 相關(guān)組件 Document 除了自身的主要邏輯:顯示主頁面之外,多了其他統(tǒng)計(jì)邏輯;

  • 如果 Document 組件的生命周期函數(shù)中,還存在其他邏輯,那么這個(gè)組件就會(huì)變的更加含糊不合理;

  • 統(tǒng)計(jì)邏輯代碼無法復(fù)用;

  • 組件重構(gòu)、維護(hù)都會(huì)變的更加困難。

  • 為了解決這個(gè)問題,我們提出了高階組件這個(gè)概念: higher-order components (HOCs)。不去晦澀地解釋這個(gè)名詞,我們來直接看看使用高階組件如何來重構(gòu)上面的代碼:

    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 函數(shù)并不會(huì)去改變 WrappedComponent 組件本身,更不會(huì)去改變 WrappedComponent 組件的行為。而是返回了一個(gè)被包裹的新組件。實(shí)際用法為:

    class Document extends React.Component {
     render() { // ...
     }
    }
    
    export default withLinkAnalytics((props) => ({
     documentId: props.documentId
    }), Document);

    這樣一來,Document 組件仍然只需關(guān)心自己該關(guān)心的部分,而 withLinkAnalytics 賦予了復(fù)用統(tǒng)計(jì)邏輯的能力。

    高階組件的存在,完美展示了 React 天生的復(fù)合(compositional)能力,在 React 社區(qū)當(dāng)中,react-redux,styled-components,react-intl 等都普遍采用了這個(gè)方式。值得一提的是,recompose 類庫又利用高階組件,并發(fā)揚(yáng)光大,做到了“腦洞大開”的事情。

    React 及其周邊社區(qū)的崛起,讓函數(shù)式編程風(fēng)靡一時(shí),受到追捧。其中關(guān)于 decomposing 和 composing 的思想,我認(rèn)為非常值得學(xué)習(xí)。同時(shí),對(duì)開發(fā)設(shè)計(jì)的一個(gè)建議是,一般情況下,不要猶豫將你的組件拆分的更小、更單一,因?yàn)檫@樣能換來強(qiáng)健和復(fù)用。

    聲明:本網(wǎng)頁內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

    文檔

    分解React組件的幾種進(jìn)階方法

    分解React組件的幾種進(jìn)階方法:React 組件魔力無窮,同時(shí)靈活性超強(qiáng)。我們可以在組件的設(shè)計(jì)上,玩轉(zhuǎn)出很多花樣。但是保證組件的Single responsibility principle: 單一原則非常重要,它可以使得我們的組件更簡(jiǎn)單、更方便維護(hù),更重要的是使得組件更加具有復(fù)用性。本文主要和大家分享分解R
    推薦度:
    標(biāo)簽: 方法 分解 的方法
    • 熱門焦點(diǎn)

    最新推薦

    猜你喜歡

    熱門推薦

    專題
    Top
    主站蜘蛛池模板: 精品久久久久久无码专区| 综合久久精品色| 亚洲精品无码你懂的网站| 四虎在线精品视频一二区| 无码人妻精品一区二区三区久久| 国产乱码伦精品一区二区三区麻豆| 99久久精品国产免看国产一区| 日韩精品一区二区亚洲AV观看| 欧美久久亚洲精品| 国精品产露脸自拍| 91精品国产高清久久久久久国产嫩草 | 亚洲精品无码久久千人斩| 国产精品亚洲美女久久久| 国产精品成人不卡在线观看| 精品人妻码一区二区三区| 亚洲AV无码久久精品色欲| 日韩一区二区精品观看| 久久久久九国产精品| 精品国产乱码久久久久久浪潮| 高清日韩精品一区二区三区| 91精品国产高清久久久久久国产嫩草| 日本欧美韩国日本精品| 国产精品三级在线| 久久99精品综合国产首页| 国产高清在线精品一区| 99精品在线观看| 91探花福利精品国产自产在线| 国产国产精品人在线视| 51视频国产精品一区二区| HEYZO无码综合国产精品| 国语自产少妇精品视频蜜桃| 精品无码人妻夜人多侵犯18 | 久久久久99精品成人片直播| 色欲精品国产一区二区三区AV | 亚洲国产精品成人精品无码区在线 | 久久精品无码专区免费东京热| 无码国产精品一区二区免费式芒果| 在线成人精品国产区免费| 亚洲国产精品久久久天堂| 久久精品夜夜夜夜夜久久| 国产精品亚洲精品日韩已满|