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