国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

React進(jìn)階——使用高階組件(Higher-order Components)優(yōu)化你的代碼

happyfish / 1798人閱讀

摘要:之所以稱之為高階,是因?yàn)樵谥校@種嵌套關(guān)系會反映到組件樹上,層層嵌套就好像高階函數(shù)的一樣,如圖從圖上也可以看出,組件樹雖然嵌套了多層,但是實(shí)際渲染的結(jié)構(gòu)并沒有改變。你可能已經(jīng)注意到,目前我寫的所有高階函數(shù),都是形如表示為。

什么是高階組件

Higher-Order Components (HOCs) are JavaScript functions which add functionality to existing component classes.

通過函數(shù)向現(xiàn)有組件類添加邏輯,就是高階組件。

讓我們先來看一個(gè)可能是史上最無聊的高階組件:

function noId() {
  return function(Comp) {
    return class NoID extends Component {
      render() {
        const {id, ...others} = this.props;
        return (
          
        )
      }
    }
  }
}

const WithoutID = noId()(Comp);

這個(gè)例子向我們展示了高階組件的工作方式:通過函數(shù)和閉包,改變已有組件的行為——這里是忽略id屬性——而完全不需要修改任何代碼。

之所以稱之為高階,是因?yàn)樵赗eact中,這種嵌套關(guān)系會反映到組件樹上,層層嵌套就好像高階函數(shù)的function in function一樣,如圖:

從圖上也可以看出,組件樹雖然嵌套了多層,但是實(shí)際渲染的DOM結(jié)構(gòu)并沒有改變。
如果你對這點(diǎn)有疑問,不妨自己寫寫例子試下,加深對React的理解。現(xiàn)在可以先記下結(jié)論:我們可以放心的使用多層高階組件,甚至重復(fù)地調(diào)用,而不必?fù)?dān)心影響輸出的DOM結(jié)構(gòu)。

借助函數(shù)的邏輯表現(xiàn)力,高階組件的用途幾乎是無窮無盡的:

適配器

有的時(shí)候你需要替換一些已有組件,而新組件接收的參數(shù)和原組件并不完全一致。

你可以修改所有使用舊組件的代碼來保證傳入正確的參數(shù)——考慮改行吧如果你真這么想

也可以把新組件做一層封裝:

class ListAdapter extends Component {
    mapProps(props) {
        return {/* new props */}
    }
    render() {
        return 
    }
}

如果有十個(gè)組件需要適配呢?如果你不想照著上面寫十遍,或許高階組件可以給你答案

function mapProps(mapFn) {
    return function(Comp) {
        return class extends Component {
            render() {
                return 
            }
        }
    } 
}

const ListAdapter = mapProps(mapPropsForNewList)(NewList);

借助高階組件,關(guān)注點(diǎn)被分離得更加干凈:只需要關(guān)注真正重要的部分——屬性的mapping。

這個(gè)例子有些價(jià)值,卻仍然不夠打動人,如果你也這么想,請往下看:

處理副作用

純組件易寫易測,越多越好,這是常識。然而在實(shí)際項(xiàng)目中,往往有許多的狀態(tài)和副作用需要處理,最常見的情況就是異步了。

假設(shè)我們需要異步加載一個(gè)用戶列表,通常的代碼可能是這樣的:

class UserList extends Component {
  constructor(props) {
    super();
    this.state = {
      list: []
    }
  }
  componentDidMount() {
    loadUsers()
      .then(data=> 
        this.setState({list: data.userList})
      )
  }
  render() {
    return (
      
    )
  }
  /* other bussiness logics */
}

實(shí)際情況中,以上代碼往往還會和其它一些業(yè)務(wù)函數(shù)混雜在一起——我們創(chuàng)建了一個(gè)業(yè)務(wù)副作用混雜的、有狀態(tài)的組件。

如果再來一個(gè)書單列表呢?再寫一個(gè)BookList然后把loadUsers改成loadBooks ?
不僅代碼重復(fù),大量有狀態(tài)和副作用的組件,也使得應(yīng)用更加難以測試。

也許你會考慮使用Flux。它確實(shí)能讓你的代碼更清晰,但是在有些場景下使用Flux就像大炮打蚊子。比如一個(gè)異步的下拉選擇框,如果要考慮復(fù)用的話,傳統(tǒng)的Flux/Reflux幾乎無法優(yōu)雅的處理,Redux稍好一些,但仍然很難做優(yōu)雅。關(guān)于flux/redux的缺點(diǎn)不深入,有興趣的可以參考Cycle.js作者的文章

回到問題的本源:其實(shí)我們只想要一個(gè)能復(fù)用的異步下拉列表而已啊!

高階函數(shù)試試?

import React, { Component } from "react";

const DEFAULT_OPTIONS = {
  mapStateToProps: undefined,
  mapLoadingToProps: loading => ({ loading }),
  mapDataToProps: data => ({ data }),
  mapErrorToProps: error => ({ error }),
};
export function connectPromise(options) {
  return (Comp) => {
    const finalOptions = {
      ...DEFAULT_OPTIONS,
      ...options,
    };
    const {
      promiseLoader,
      mapLoadingToProps,
      mapStateToProps,
      mapDataToProps,
      mapErrorToProps,
    } = finalOptions;

    class AsyncComponent extends Component {
      constructor(props) {
        super(props);
        this.state = {
          loading: true,
          data: undefined,
          error: undefined,
        };
      }
      componentDidMount() {
        promiseLoader(this.props)
          .then(
            data => this.setState({ data, loading: false }),
            error => this.setState({ error, loading: false }),
          );
      }
      render() {
        const { data, error, loading } = this.state;

        const dataProps = data ? mapDataToProps(data) : undefined;
        const errorProps = error ? mapErrorToProps(error) : undefined;

        return (
          
        );
      }
    }

    return AsyncComponent;
  };
}


const UserList = connectPromise({
    promiseLoader: loadUsers,
    mapDataToProps: result=> ({list: result.userList})
})(List); //List can be a pure component

const BookList = connectPromise({
    promiseLoader: loadBooks,
    mapDataToProps: result=> ({list: result.bookList})
})(List);

不僅大大減少了重復(fù)代碼,還把散落各處的異步邏輯裝進(jìn)了可以多帶帶管理和測試的籠子,在業(yè)務(wù)場景中,只需要純組件 + 配置 就能實(shí)現(xiàn)相同的功能——而無論是純組件還是配置,都是對單元測試友好的,至少比異步組件友好多了。

使用curry & compose

高階組件的另一個(gè)亮點(diǎn),就是對函數(shù)式編程的友好。你可能已經(jīng)注意到,目前我寫的所有高階函數(shù),都是形如:

config => {
    return Component=> {
        return HighOrderCompoent
    }
}

表示為config=> Component=> Component

寫成嵌套的函數(shù)是為了手動curry化,而參數(shù)的順序(為什么不是Component=> config=> Component),則是為了組合方便。關(guān)于curry與compose的使用,可以移步我的另一篇blog

舉個(gè)栗子,前面講了適配器和異步,我們可以很快就組合出兩者的結(jié)合體:使用NewList的異步用戶列表

UserList = compose(
  connectPromise({
    promiseLoader: loadUsers,
    mapResultToProps: result=> ({list: result.userList})
  }),
  mapProps(mapPropsForNewList)
)(NewList);
總結(jié)

在團(tuán)隊(duì)內(nèi)部分享里,我的總結(jié)是三個(gè)詞 Easy, Light-weight & Composable.

其實(shí)高階組件并不是什么新東西,本質(zhì)上就是Decorator模式在React的一種實(shí)現(xiàn),但在相當(dāng)一段時(shí)間內(nèi),這個(gè)優(yōu)秀的模式都被人忽略。在我看來,大部分使用mixinclass extends的地方,高階組件都是更好的方案——畢竟組合優(yōu)于繼承,而mixin——個(gè)人覺得沒資格參與討論。

使用高階組件還有兩個(gè)好處:

適用范圍廣,它不需要es6或者其它需要編譯的特性,有函數(shù)的地方,就有HOC。

Debug友好,它能夠被React組件樹顯示,所以可以很清楚地知道有多少層,每層做了什么。相比之下無論是mixin還是繼承,都顯得非常隱晦。

值得慶幸的是,社區(qū)也明顯注意到了高階組件的價(jià)值,無論是大家非常熟悉的react-redux 的connect函數(shù),還是redux-form,高階組件的應(yīng)用開始隨處可見。

下次當(dāng)你想寫mixinclass extends的時(shí)候,不妨也考慮下高階組件。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/78902.html

相關(guān)文章

  • React 高階組件(HOC)實(shí)踐

    摘要:簡單來說高階組件就是一個(gè)函數(shù),它接受一個(gè)組件作為參數(shù)然后返回一個(gè)新組件。主要用于組件之間邏輯復(fù)用。使用由于數(shù)據(jù)請求是異步的,為了不讓用戶看到一片空白,當(dāng)數(shù)據(jù)請求還沒有返回時(shí),展示組件。組合函數(shù),提升代碼可閱讀性。 簡單來說高階組件(HOC)就是一個(gè)函數(shù),它接受一個(gè)組件作為參數(shù)然后返回一個(gè)新組件。HOC 主要用于組件之間邏輯復(fù)用。比如你寫了幾個(gè)組件,他們之間的邏輯幾乎相同,就可以用 HOC 對...

    caiyongji 評論0 收藏0
  • React進(jìn)階系列】手寫實(shí)現(xiàn)react-redux api

    簡介:簡單實(shí)現(xiàn)react-redux基礎(chǔ)api react-redux api回顧 把store放在context里,所有子組件可以直接拿到store數(shù)據(jù) 使組件層級中的 connect() 方法都能夠獲得 Redux store 根組件應(yīng)該嵌套在 中 ReactDOM.render( , rootEl ) ReactDOM.render( ...

    劉玉平 評論0 收藏0
  • React 組件設(shè)計(jì)和分解思考

    摘要:我們可以在組件的設(shè)計(jì)上,玩轉(zhuǎn)出很多花樣。但是,如何對一個(gè)功能復(fù)雜且臃腫的組件進(jìn)行分解,也許并不是一件簡單的事情。同時(shí),借助于新的算法引擎,兩個(gè)單元組件在渲染的效率上,樂觀地預(yù)計(jì)會有較大幅度的提升。 之前分享過幾篇關(guān)于React技術(shù)棧的文章: 做出Uber移動網(wǎng)頁版還不夠 極致性能打造才見真章 解析Twitter前端架構(gòu) 學(xué)習(xí)復(fù)雜場景數(shù)據(jù)設(shè)計(jì) React Conf 2017 干貨總結(jié)1...

    liukai90 評論0 收藏0
  • 寫一本關(guān)于 React.js 的小書

    摘要:因?yàn)楣ぷ髦幸恢痹谑褂茫惨恢币詠硐肟偨Y(jié)一下自己關(guān)于的一些知識經(jīng)驗(yàn)。于是把一些想法慢慢整理書寫下來,做成一本開源免費(fèi)專業(yè)簡單的入門級別的小書,提供給社區(qū)。本書的后續(xù)可能會做成視頻版本,敬請期待。本作品采用署名禁止演繹國際許可協(xié)議進(jìn)行許可 React.js 小書 本文作者:胡子大哈本文原文:React.js 小書 轉(zhuǎn)載請注明出處,保留原文鏈接以及作者信息 在線閱讀:http://huzi...

    Scorpion 評論0 收藏0
  • React高階組件(HOC)模型理論與實(shí)踐

    摘要:栗子的方法就是一個(gè),他獲取,在中給添加需要的。本來準(zhǔn)備把詳細(xì)代碼當(dāng)個(gè)栗子貼出來的,結(jié)果突然想到公司保密協(xié)議,所以。。。栗子這樣子你就可以在父組件中這樣獲取的值了。 什么是HOC? HOC(全稱Higher-order component)是一種React的進(jìn)階使用方法,主要還是為了便于組件的復(fù)用。HOC就是一個(gè)方法,獲取一個(gè)組件,返回一個(gè)更高級的組件。 什么時(shí)候使用HOC? 在Reac...

    Leo_chen 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<