摘要:栗子的方法就是一個,他獲取,在中給添加需要的。本來準備把詳細代碼當個栗子貼出來的,結果突然想到公司保密協議,所以。。。栗子這樣子你就可以在父組件中這樣獲取的值了。
什么是HOC?
HOC(全稱Higher-order component)是一種React的進階使用方法,主要還是為了便于組件的復用。HOC就是一個方法,獲取一個組件,返回一個更高級的組件。
什么時候使用HOC?在React開發過程中,發現有很多情況下,組件需要被"增強",比如說給組件添加或者修改一些特定的props,一些權限的管理,或者一些其他的優化之類的。而如果這個功能是針對多個組件的,同時每一個組件都寫一套相同的代碼,明顯顯得不是很明智,所以就可以考慮使用HOC。
栗子:react-redux的connect方法就是一個HOC,他獲取wrappedComponent,在connect中給wrappedComponent添加需要的props。
HOC的簡單實現HOC不僅僅是一個方法,確切說應該是一個組件工廠,獲取低階組件,生成高階組件。
一個最簡單的HOC實現是這個樣子的:
function HOCFactory(WrappedComponent) { return class HOC extends React.Component { render(){ returnHOC可以做什么?} } }
代碼復用,代碼模塊化
增刪改props
渲染劫持
其實,除了代碼復用和模塊化,HOC做的其實就是劫持,由于傳入的wrappedComponent是作為一個child進行渲染的,上級傳入的props都是直接傳給HOC的,所以HOC組件擁有很大的權限去修改props和控制渲染。
增刪改props可以通過對傳入的props進行修改,或者添加新的props來達到增刪改props的效果。
比如你想要給wrappedComponent增加一個props,可以這么搞:
function control(wrappedComponent) { return class Control extends React.Component { render(){ let props = { ...this.props, message: "You are under control" }; return} } }
這樣,你就可以在你的組件中使用message這個props:
class MyComponent extends React.Component { render(){ return渲染劫持{this.props.message}} } export default control(MyComponent);
這里的渲染劫持并不是你能控制它渲染的細節,而是控制是否去渲染。由于細節屬于組件內部的render方法控制,所以你無法控制渲染細節。
比如,組件要在data沒有加載完的時候,現實loading...,就可以這么寫:
function loading(wrappedComponent) { return class Loading extends React.Component { render(){ if(!this.props.data) { returnloading...} return} } }
這個樣子,在父級沒有傳入data的時候,這一塊兒就只會顯示loading...,不會顯示組件的具體內容
class MyComponent extends React.Component { render(){ returnHOC有什么用例? React Redux{this.props.data}} } export default control(MyComponent);
最經典的就是React Redux的connect方法(具體在connectAdvanced中實現)。
通過這個HOC方法,監聽redux store,然后把下級組件需要的state(通過mapStateToProps獲取)和action creator(通過mapDispatchToProps獲取)綁定到wrappedComponent的props上。
logger和debugger這個是官網上的一個示例,可以用來監控父級組件傳入的props的改變:
function logProps(WrappedComponent) { return class extends React.Component { componentWillReceiveProps(nextProps) { console.log(`WrappedComponent: ${WrappedComponent.displayName}, Current props: `, this.props); console.log(`WrappedComponent: ${WrappedComponent.displayName}, Next props: `, nextProps); } render() { // Wraps the input component in a container, without mutating it. Good! return頁面權限管理; } } }
可以通過HOC對組件進行包裹,當跳轉到當前頁面的時候,檢查用戶是否含有對應的權限。如果有的話,渲染頁面。如果沒有的話,跳轉到其他頁面(比如無權限頁面,或者登陸頁面)。
也可以給當前組件提供權限的API,頁面內部也可以進行權限的邏輯判斷。
本來準備把詳細代碼當個栗子貼出來的,結果突然想到公司保密協議,所以。。。
使用HOC需要注意什么? 盡量不要隨意修改下級組件需要的props之所以這么說,是因為修改父級傳給下級的props是有一定風險的,可能會造成下級組件發生錯誤。比如,原本需要一個name的props,但是在HOC中給刪掉了,那么下級組件或許就無法正常渲染,甚至報錯。
Ref無法獲取你想要的ref以前你在父組件中使用
要解決這個問題,這里有兩個方法:
a) 像React Redux的connect方法一樣,在里面添加一個參數,比如withRef,組件中檢查到這個flag了,就給下級組件添加一個ref,并通過getWrappedInstance方法獲取。
栗子:
function HOCFactory(wrappedComponent) { return class HOC extends React.Component { getWrappedInstance = ()=>{ if(this.props.widthRef) { return this.wrappedInstance; } } setWrappedInstance = (ref)=>{ this.wrappedInstance = ref; } render(){ let props = { ...this.props }; if(this.props.withRef) { props.ref = this.setWrappedInstance; } return} } } export default HOCFactory(MyComponent);
這樣子你就可以在父組件中這樣獲取MyComponent的ref值了。
class ParentCompoent extends React.Component { doSomethingWithMyComponent(){ let instance = this.refs.child.getWrappedInstance(); // .... } render(){ return} }
b) 還有一種方法,在官網中有提到過:
父級通過傳遞一個方法,來獲取ref,具體看栗子:
先看父級組件:
class ParentCompoent extends React.Component { getInstance = (ref)=>{ this.wrappedInstance = ref; } render(){ return} }
HOC里面把getInstance方法當作ref的方法傳入就好
function HOCFactory(wrappedComponent) { return class HOC extends React.Component { render(){ let props = { ...this.props }; if(typeof this.props.getInstance === "function") { props.ref = this.props.getInstance; } return} } } export default HOCFactory(MyComponent);
感謝@wmzy的指出,在上面的兩個方法getInstance和setWrappedInstance,由于ES6 class的寫法并不會自動綁定this,所以需要用bind(this)到兩個方法上,確保this的正確性。或者使用箭頭函數來寫兩個方法,ES6的箭頭函數會自動綁定this。Component上面綁定的Static方法會丟失
比如,你原來在Component上面綁定了一些static方法MyComponent.staticMethod = o=>o。但是由于經過HOC的包裹,父級組件拿到的已經不是原來的組件了,所以當然無法獲取到staticMethod方法了。
官網上的示例:
// 定義一個static方法 WrappedComponent.staticMethod = function() {/*...*/} // 利用HOC包裹 const EnhancedComponent = enhance(WrappedComponent); // 返回的方法無法獲取到staticMethod typeof EnhancedComponent.staticMethod === "undefined" // true
這里有一個解決方法,就是hoist-non-react-statics組件,這個組件會自動把所有綁定在對象上的非React方法都綁定到新的對象上:
import hoistNonReactStatic from "hoist-non-react-statics"; function enhance(WrappedComponent) { class Enhance extends React.Component {/*...*/} hoistNonReactStatic(Enhance, WrappedComponent); return Enhance; }結束語
當你需要做React插件的時候,HOC模型是一個很實用的模型。
希望這篇文章能幫你對HOC有一個大概的了解和啟發。
另外,這篇medium上的文章會給你更多的啟發,在這篇文章中,我這里講的被分為Props Proxy HOC,還有另外一種Inheritance Inversion HOC,強烈推薦看一看。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/81199.html
摘要:簡單來說高階組件就是一個函數,它接受一個組件作為參數然后返回一個新組件。主要用于組件之間邏輯復用。使用由于數據請求是異步的,為了不讓用戶看到一片空白,當數據請求還沒有返回時,展示組件。組合函數,提升代碼可閱讀性。 簡單來說高階組件(HOC)就是一個函數,它接受一個組件作為參數然后返回一個新組件。HOC 主要用于組件之間邏輯復用。比如你寫了幾個組件,他們之間的邏輯幾乎相同,就可以用 HOC 對...
摘要:原文鏈接高階組件在中是組件復用的一個強大工具。在本文中,高階組件將會被分為兩種基本模式,我們將其命名為和用附加的功能來包裹組件。這里我們使用泛型表示傳遞到的組件的。在這里,我們定義從返回的組件,并指定該組件將包括傳入組件的和的。 原文鏈接:https://medium.com/@jrwebdev/... 高階組件(HOCs)在React中是組件復用的一個強大工具。但是,經常有開發者在...
摘要:在深入技術棧一書中,提到了基于的。書里對基于的沒有給出完整的實現,在這里實現并記錄一下實現的思路。在這里最小的組件就是。對比范式與父組件的范式,如果完全利用來實現的,將操作與分離,也未嘗不可,但卻不優雅。 在深入react 技術棧一書中,提到了基于Decorator的HOC。而不是直接通過父組件來逐層傳遞props,因為當業務邏輯越來越復雜的時候,props的傳遞和維護也將變得困難且冗...
摘要:啟動項目教程最終的目的是構建一個帶有趣的應用程序來自,可以在視口周圍拖動。創建組件,添加樣式和數據為簡單起見,我們將在文件中編寫所有樣式。可以看出,就是在當前的外層包裹我們所需要實現的功能。現在已經知道如何在項目中實現拖放 翻譯:https://css-tricks.com/draggi... React 社區提供了許多的庫來實現拖放的功能,例如 react-dnd, react-b...
閱讀 3011·2021-10-27 14:15
閱讀 2999·2021-09-07 10:18
閱讀 1320·2019-08-30 15:53
閱讀 1570·2019-08-26 18:18
閱讀 3373·2019-08-26 12:15
閱讀 3460·2019-08-26 10:43
閱讀 654·2019-08-23 16:43
閱讀 2207·2019-08-23 15:27