最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

React高階組件使用教程詳解

 更新時間:2022年12月02日 17:00:38   作者:碼農(nóng)小菲  
高階組件就是接受一個組件作為參數(shù)并返回一個新組件(功能增強(qiáng)的組件)的函數(shù)。這里需要注意高階組件是一個函數(shù),并不是組件,這一點一定要注意,本文給大家分享React 高階組件HOC使用小結(jié),一起看看吧

高階組件(HOC)

概述

是React復(fù)用組件邏輯的一種高級技巧,是一種基于React組合特性而形成的設(shè)計模式

高階組件是參數(shù)為組件,返回值為新組件的函數(shù)

簡單理解:

  • 高階組件本身是 函數(shù),傳參數(shù)是組件,返回值也是組件;
  • 高階組件不用關(guān)心數(shù)據(jù)是如何渲染的,只用關(guān)心邏輯即可
  • 被包裝的組件本身不用關(guān)心數(shù)據(jù)是怎么來的,只用負(fù)責(zé)渲染即可
  • 最后渲染的是高階組件返回的組件

高階組件的調(diào)用過程類似于這樣:

const EnhancedComponent = higherOrderComponent(WrappedComponent);

應(yīng)用場景:redux 中的 connect

具體怎么編寫呢?往下看…

使用HOC解決橫切關(guān)注點問題

橫切關(guān)注點問題:指的是一些具有橫越多個模塊的行為,使用傳統(tǒng)的軟件開發(fā)方法不能夠達(dá)到有效的模塊化的一類特殊關(guān)注點。

組件是React 中代碼復(fù)用的基本單元,但某些模式并不適合傳統(tǒng)組件

假設(shè)有一個 CommentList 組件,訂閱外部數(shù)據(jù)源,用于渲染評論列表:

class CommentList extends React.Component {
   constructor(props) {
     super(props);
     this.handleChange = this.handleChange.bind(this);
     this.state = {
       // 假設(shè) "DataSource" 是個全局范圍內(nèi)的數(shù)據(jù)源變量,來自外部,自身帶有很多方法
       comments: DataSource.getComments()  //假設(shè)getComments()這個方法可以獲取所有的評論
     };
   }
   componentDidMount() {
     // 訂閱更改;監(jiān)聽  DataSource ,發(fā)生變化時更新數(shù)據(jù)
     DataSource.addChangeListener(this.handleChange);
   }
   componentWillUnmount() {
     // 清除訂閱
     DataSource.removeChangeListener(this.handleChange);
   }
   handleChange() {
     // 當(dāng)數(shù)據(jù)源更新時,更新組件狀態(tài)
     this.setState({
       comments: DataSource.getComments()  //假設(shè)getComments()這個方法可以獲取所有的評論
     });
   }
   render() {
     return (
       <div>
         {this.state.comments.map((comment) => (
           <Comment comment={comment} key={comment.id} />
         ))}
       </div>
     );
   }
 }
 // 假設(shè) DataSource:來自外部;它自身有很多方法,如:getComments(),addChangeListener,removeChangeListener 等
//  假設(shè) <Comment /> 是子組件,父組件 CommentList 需要將 comment 、key 傳遞給它

假設(shè)有個 訂閱單個博客帖子的組件BlogPost,與上面的模式類似:

class BlogPost extends React.Component {
 constructor(props) {
   super(props);
   this.handleChange = this.handleChange.bind(this);
   this.state = {
     blogPost: DataSource.getBlogPost(props.id)
   };
 }
 componentDidMount() {
   DataSource.addChangeListener(this.handleChange);
 }
 componentWillUnmount() {
   DataSource.removeChangeListener(this.handleChange);
 }
 handleChange() {
   this.setState({
     blogPost: DataSource.getBlogPost(this.props.id)
   });
 }
 render() {
   return <TextBlock text={this.state.blogPost} />;
 }
}

以上兩個組件的不同點

  • 調(diào)用方法不用

以上兩個組件的相同點

  • 在掛載時,向 DataSource 添加一個更改偵 聽器在偵 聽器
  • 內(nèi)部,當(dāng)數(shù)據(jù)源發(fā)生變化時,調(diào)用 setState
  • 在卸載時,刪除偵 聽器

上面兩個組件相同點的地方被不斷的重復(fù)調(diào)用,在大型項目中,所以我們需要將這些共同使用的地方給抽象出來,然后讓許多組件之間共享它,這正是高階組件擅長的地方。

編寫一個創(chuàng)建組件函數(shù),這個函數(shù)接收兩個參數(shù),一個是要被包裝的子組件,另一個則是該子組件訂閱數(shù)據(jù)的函數(shù)。

 const CommentListWithSubscription = withSubscription(
    CommentList,
    (DataSource) => DataSource.getComments()
  );
  const BlogPostWithSubscription = withSubscription(
    BlogPost,
    (DataSource, props) => DataSource.getBlogPost(props.id)
  );
//以上寫法相當(dāng)于高級組件的調(diào)用,withSubscription為自定義的高階組件;CommentList:被包裝的子組件;CommentListWithSubscription:返回的包裝后的組件

當(dāng)渲染 CommentListWithSubscription 和 BlogPostWithSubscription 時, CommentList 和 BlogPost 將傳遞一個 data prop,其中包含從 DataSource 檢索到的最新數(shù)據(jù)

 // 此函數(shù)接收一個組件...
function withSubscription(WrappedComponent, selectData) {
 // ...并返回另一個組件...
 return class extends React.Component {
   constructor(props) {
     super(props);
     this.handleChange = this.handleChange.bind(this);
     this.state = {
       data: selectData(DataSource, props)
     };
   }
   componentDidMount() {
     // ...負(fù)責(zé)訂閱相關(guān)的操作...
     DataSource.addChangeListener(this.handleChange);
   }
   componentWillUnmount() {
     DataSource.removeChangeListener(this.handleChange);
   }
   handleChange() {
     this.setState({
       data: selectData(DataSource, this.props)
     });
   }
   render() {
     // ... 并使用新數(shù)據(jù)渲染被包裝的組件!
     // 請注意,我們可能還會傳遞其他屬性
     return <WrappedComponent data={this.state.data} {...this.props} />;
   }
 };
}

HOC不會修改傳入的組件,也不會使用繼承來復(fù)制其行為,相反HOC是通過將組件包裝在容器組件中來組成新的組件,HOC是純函數(shù),沒有副作用

  • 被包裝組件接收來自容器組件的所有prop,同時也接收一個新的用于render的data prop
  • HOC不用關(guān)心數(shù)據(jù)的使用方式,被包裝組件也不用關(guān)心數(shù)據(jù)是怎么來的

不用改變原始組件使用組合

不要試圖在 HOC 中修改組件原型(或以其他方式改變它)

function logProps(InputComponent) {
 InputComponent.prototype.componentDidUpdate = function(prevProps) {
   console.log('Current props: ', this.props);
   console.log('Previous props: ', prevProps);
 };
 // 返回原始的 input 組件,暗示它已經(jīng)被修改。
 return InputComponent;
}
// 每次調(diào)用 logProps 時,增強(qiáng)組件都會有 log 輸出。
const EnhancedComponent = logProps(InputComponent)
//上面這種寫法會造成另一個同樣會修改componentDidUpate的HOC增強(qiáng)它,那么前面的HOC就會失效。

HOC不應(yīng)該修改傳入組件,而應(yīng)該使用組合的方式,將組件包裝在容器組件中實現(xiàn)功能。

function logProps(WrappedComponent) {
    return class extends React.Component {
      componentDidUpdate(prevProps) {
        console.log('Current props: ', this.props);
        console.log('Previous props: ', prevProps);
      }
      render() {
        // 將 input 組件包裝在容器中,而不對其進(jìn)行修改。Good!
        return <WrappedComponent {...this.props} />;
      }
    }
  }

約定-將不相關(guān)的 props 傳遞給被包裹的組件

HOC為組件添加特性,自身不應(yīng)該大幅改變約定,HOC應(yīng)該透傳與自身無關(guān)的props,大多數(shù)HOC都應(yīng)該包含一個類似于下面的render方法

render() {
  // 過濾掉非此 HOC 額外的 props,且不要進(jìn)行透傳
  const { extraProp, ...passThroughProps } = this.props;
  // 將 props 注入到被包裝的組件中。
  // 通常為 state 的值或者實例方法。
  const injectedProp = someStateOrInstanceMethod;
  // 將 props 傳遞給被包裝組件
  return (
    <WrappedComponent
      injectedProp={injectedProp}
      {...passThroughProps}
    />
  );
}	

約定-最大化可組合性

有時候它僅接受一個參數(shù),也就是被包裹的組件:

const NavbarWithRouter = withRouter(Navbar);

HOC通常也可以接收多個參數(shù)

const CommentWithRelay = Relay.createContainer(Comment, config);

常見的HOC簽名(React Redux的connect函數(shù)):

// React Redux 的 `connect` 函數(shù)const ConnectedComment = connect(commentSelector, commentActions)(CommentList);

拆分connect函數(shù)

  // connect 是一個函數(shù),它的返回值為另外一個函數(shù)。
  const enhance = connect(commentListSelector, commentListActions)
  // 返回值為 HOC,它會返回已經(jīng)連接 Redux store 的組件
 const ConnectedComment = enhance(CommentList);

約定-包裝顯示名稱以便輕松調(diào)試

HOC創(chuàng)建的容器組件會和任何其他組件一樣,顯示在React Developer Tools中,為了方便調(diào)試,需要選擇顯示一個名稱,以表明他是HOC的產(chǎn)物

function withSubscription(WrappedComponent) {
 class WithSubscription extends React.Component {/* ... */}
 WithSubscription.displayName = `WithSubscription(${getDisplayName(WrappedComponent)})`;
 return WithSubscription;
}
function getDisplayName(WrappedComponent) {
 return WrappedComponent.displayName || WrappedComponent.name || 'Component';
}

使用高階組件的注意事項

不要在render方法中使用HOC

render() {
  // 每次調(diào)用 render 函數(shù)都會創(chuàng)建一個新的 EnhancedComponent
  // EnhancedComponent1 !== EnhancedComponent2
  const EnhancedComponent = enhance(MyComponent);
  // 這將導(dǎo)致子樹每次渲染都會進(jìn)行卸載,和重新掛載的操作!
  return <EnhancedComponent />;
}

務(wù)必復(fù)制靜態(tài)方法

   // 定義靜態(tài)函數(shù)
 WrappedComponent.staticMethod = function() {/*...*/}
 // 現(xiàn)在使用 HOC
 const EnhancedComponent = enhance(WrappedComponent);
 // 增強(qiáng)組件沒有 staticMethod
 typeof EnhancedComponent.staticMethod === 'undefined' // true
//為了解決這個問題,你可以在返回之前把這些方法拷貝到容器組件上:
function enhance(WrappedComponent) {
   class Enhance extends React.Component {/*...*/}
   // 必須準(zhǔn)確知道應(yīng)該拷貝哪些方法 :(
   Enhance.staticMethod = WrappedComponent.staticMethod;
   return Enhance
 }

Refs 不會被傳遞

雖然高階組件的約定是將所有 props 傳遞給被包裝組件,但這對于 refs 并不適用。那是因為 ref 實際上并不是一個 prop - 就像 key 一樣,它是由 React 專門處理的。如果將 ref 添加到 HOC 的返回組件中,則 ref 引用指向容器組件,而不是被包裝組件。

到此這篇關(guān)于React高階組件使用教程詳解的文章就介紹到這了,更多相關(guān)React高階組件內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • react實現(xiàn)可播放的進(jìn)度條

    react實現(xiàn)可播放的進(jìn)度條

    這篇文章主要為大家詳細(xì)介紹了react實現(xiàn)可播放的進(jìn)度條,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • React Router6.x路由表封裝的兩種寫法

    React Router6.x路由表封裝的兩種寫法

    本文主要介紹了React Router6.x路由表封裝的兩種寫法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-01-01
  • React?Hooks項目實戰(zhàn)

    React?Hooks項目實戰(zhàn)

    React?Hooks是React?16.8版本引入的新特性,它使得在函數(shù)組件中也能夠使用狀態(tài)(state)和其他React特性,本文就來詳細(xì)介紹一下React?Hooks項目實戰(zhàn),感興趣的可以了解一下
    2023-11-11
  • react native帶索引的城市列表組件的實例代碼

    react native帶索引的城市列表組件的實例代碼

    本篇文章主要介紹了react-native城市列表組件的實例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-08-08
  • react中實現(xiàn)修改input的defaultValue

    react中實現(xiàn)修改input的defaultValue

    這篇文章主要介紹了react中實現(xiàn)修改input的defaultValue方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-05-05
  • React組件通信的實現(xiàn)示例

    React組件通信的實現(xiàn)示例

    在React中,組件通信是一個重要的概念,它允許不同組件之間進(jìn)行數(shù)據(jù)傳遞和交互,本文主要介紹了React組件通信的實現(xiàn)示例,感興趣的可以了解一下
    2023-11-11
  • 模塊化react-router配置方法詳解

    模塊化react-router配置方法詳解

    這篇文章主要介紹了模塊化react-router配置方法詳解,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-06-06
  • ahooks?useRequest源碼精讀解析

    ahooks?useRequest源碼精讀解析

    這篇文章主要為大家介紹了ahooks?useRequest的源碼精讀解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-07-07
  • antd+react中upload手動上傳單限制上傳一張

    antd+react中upload手動上傳單限制上傳一張

    本文主要介紹了antd+react中upload手動上傳單限制上傳一張,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-06-06
  • React?跨端動態(tài)化核心技術(shù)實例分析

    React?跨端動態(tài)化核心技術(shù)實例分析

    這篇文章主要為大家介紹了React?跨端動態(tài)化核心技術(shù)實例分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-10-10

最新評論

南安市| 镇康县| 中西区| 孝昌县| 绥中县| 大埔县| 金寨县| 阿克苏市| 锡林郭勒盟| 万盛区| 商丘市| 榆树市| 德阳市| 鲁山县| 秭归县| 轮台县| 霍邱县| 通化市| 鹤庆县| 海伦市| 马公市| 鄂伦春自治旗| 漯河市| 隆安县| 潜江市| 宿松县| 建水县| 凤山市| 黔西| 台南县| 鄂托克前旗| 桂平市| 岑溪市| 东丽区| 瓮安县| 兴安县| 井陉县| 崇仁县| 香格里拉县| 四会市| 宁夏|