摘要:在深入技術(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ù)也將變得困難且冗余。
書(shū)里對(duì)基于Decorator的HOC沒(méi)有給出完整的實(shí)現(xiàn),在這里實(shí)現(xiàn)并記錄一下實(shí)現(xiàn)的思路。
整個(gè)實(shí)現(xiàn)的代碼放到了我的Github上,是用來(lái)獲取豆瓣的電影列表的,npm start即可開(kāi)箱。
整體思路書(shū)里描述的整體思路,先將整個(gè)組件,按照view邏輯抽象為互不重疊的最小的原子組件,使組件間組合更自由。在這里最小的組件就是SearchInput SelectInput List。原子組件一定是純粹的、木偶式的組件,如果他們自身帶有復(fù)雜的交互/業(yè)務(wù)邏輯,那么在組合起來(lái)以后可想需要修改多少個(gè)原子組件,也就失去了相對(duì)配置式的優(yōu)勢(shì)。
組件實(shí)現(xiàn) 原子組件這是對(duì)原書(shū)代碼稍加修改的SearchInput原子組件,因?yàn)闆](méi)加Icon,所以改了一下(逃),整體思路不變。原子組件沒(méi)什么可說(shuō)的,木偶組件就是接收props來(lái)實(shí)現(xiàn)功能,是對(duì)view層邏輯的抽象。
需要一提的是displayName,是用來(lái)確定組件的『身份』的,會(huì)被包裹它的組合組件用到,后面會(huì)提到組合組件。
export default class SearchInput extends PureComponent { static displayName = "SearchInput" render() { const { onSearch, placeholder } = this.props return (Decorator組件) } }SearchSelect
先放代碼
const searchDecorator = WrappedComponent => { class SearchDecorator extends Component { constructor(props) { super(props) this.handleSearch = this.handleSearch.bind(this) this.state = { keyword: "" } } handleSearch(e) { this.setState({ keyword: e.target.value }) this.props.onSearch(e) } render() { const { keyword } = this.state return () } }
Decorator的作用就是將業(yè)務(wù)/交互邏輯抽象出來(lái)進(jìn)行了處理,view的邏輯還是交由原子組件來(lái)實(shí)現(xiàn),可以看到最后的render渲染的還是wrappedComponent,只不過(guò)是在經(jīng)過(guò)Decorator之后多了幾個(gè)props,這些props的中有鉤子函數(shù),有要傳遞給原子組件的參數(shù)。
這樣,視圖邏輯就由view層抽象,交互/業(yè)務(wù)邏輯由Decorator來(lái)抽象。
組合組件先上代碼。
export default class Selector extends Component { render() { return ({ this.props.children.map((item) => { // SelectInput if (item.type.displayName === "SelectInput") { ... } // SearchInput if (item.type.displayName === "SearchInput") { return React.cloneElement(item, { key: "searchInput", onSearch: this.props.onSearch, placeholder: this.props.searchPlaceholder } ) } // List if (item.type.displayName === "List") { ... }) }) } }
組合組件的children為根據(jù)不同業(yè)務(wù)需要包裹起來(lái)的原子組件,組合組件的邏輯處理功能來(lái)自于Decorator,各種Decorator的鉤子函數(shù)或者參數(shù)作為props傳遞給了Selector,Selector再用它們?nèi)ネ瓿稍咏M件之間的交互。組合組件通過(guò)之前提到的displayName為不同的原子組件分配props并根據(jù)業(yè)務(wù)需要進(jìn)行組件間邏輯交互的調(diào)整。
一個(gè) Decorator 只做最簡(jiǎn)單的邏輯,只是給組件增加一個(gè)原子的智能特性。業(yè)務(wù)組件通過(guò)組織和拼接 Decorator 來(lái)實(shí)現(xiàn)功能,而不是改變 Decorator 本身的邏輯。
當(dāng)我們業(yè)務(wù)邏輯變得復(fù)雜的時(shí)候,不要去增加Decorator的復(fù)雜度,而是去拼接多個(gè)Decorator再通過(guò)組合組件去處理具體的業(yè)務(wù)邏輯,這樣能保證Decorator的可復(fù)用性。
業(yè)務(wù)組件const FinalSelector = compose(asyncSelectDecorator, selectedItemDecorator, searchDecorator)(Selector) class SearchSelect extends Component { render() { return () } } class App extends Component { render() { return (
{ console.log(`自定義onSearch: ${e.target.value}`) }} onClick={(text) => { console.log(`自定義onClick: ${text}`) }} url="/v2/movie/in_theaters" /> ) } }
通過(guò)compose賦予組合組件不同的邏輯處理功能,然后根據(jù)業(yè)務(wù)需要讓compose后的組合組件包含原子組件,最后給從最外層傳遞參數(shù)就完成了。
tips在實(shí)際的場(chǎng)景中也不能濫用HOC,基于Decorator的HOC一般是用來(lái)處理偏數(shù)據(jù)邏輯的部分,而DOM相關(guān)的東西就直接簡(jiǎn)單粗暴的用父組件就好了。
參考資料對(duì)比 HOC 范式 compose(render)(state) 與父組件(Parent Component)的范式 render(render(state)),如果完全利用 HOC 來(lái)實(shí)現(xiàn) React 的 implement,將操作與 view 分離,也未嘗不可,但卻不優(yōu)雅。HOC 本質(zhì)上是統(tǒng)一功能抽象,強(qiáng)調(diào)邏輯與 UI 分離。但在實(shí)際開(kāi)發(fā)中,前端無(wú)法逃離 DOM ,而邏輯與 DOM 的相關(guān)性主要呈現(xiàn) 3 種關(guān)聯(lián)形式:
與 DOM 相關(guān),建議使用父組件,類似于原生 HTML 編寫(xiě)
與 DOM 不相關(guān),如校驗(yàn)、權(quán)限、請(qǐng)求發(fā)送、數(shù)據(jù)轉(zhuǎn)換這類,通過(guò)數(shù)據(jù)變化間接控制 DOM,可以使用 HOC 抽象
交叉的部分,DOM 相關(guān),但可以做到完全內(nèi)聚,即這些 DOM 不會(huì)和外部有關(guān)聯(lián),均可
深入react 技術(shù)棧
基于Decorator的組件擴(kuò)展實(shí)踐
精讀 React 高階組件
深入理解 React 高階組件
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/89607.html
摘要:為了代碼進(jìn)一步解耦,可以考慮使用高階組件這種模式。開(kāi)源的高階組件使用提供了一系列使用的高階組件,可以增強(qiáng)組件的行為,可以利用此庫(kù)學(xué)習(xí)高階組件的寫(xiě)法。通過(guò)使用此庫(kù)提供的高階組件,可以方便地讓列表元素可拖動(dòng)。 1. Decorator基本知識(shí) 在很多框架和庫(kù)中看到它的身影,尤其是React和Redux,還有mobx中,那什么是裝飾器呢。 修飾器(Decorator)是一個(gè)函數(shù),用來(lái)修改類的...
摘要:在業(yè)務(wù)統(tǒng)一的情況下,僅僅修改組件用于配置的就可以滿足業(yè)務(wù)需求。避免了復(fù)雜的圖表配置,而將圖表進(jìn)行有效拆分,通過(guò)聲明式的標(biāo)簽進(jìn)行組合,從而使圖表更具擴(kuò)展性。而對(duì)于顆粒度最細(xì)的組件,我們希望它是純粹的,木偶式的組件。 在前端業(yè)務(wù)開(kāi)發(fā)中,組件化已經(jīng)成為我們的共識(shí)。沉淀和復(fù)用組件,是提高開(kāi)發(fā)效率的利器。但在組件復(fù)用的過(guò)程中,我們往往會(huì)遇到這樣的問(wèn)題,組件相似,卻在結(jié)構(gòu)或交互上有些許差別,需要對(duì)...
摘要:博客地址背景知識(shí)在開(kāi)始講述高階組件前,我們先來(lái)回顧高階函數(shù)的定義接收函數(shù)作為輸入,或者輸出另一個(gè)函數(shù)的一類函數(shù),被稱作高階函數(shù)。 博客地址:http://www.luckyjing.com/post... 背景知識(shí) 在開(kāi)始講述高階組件前,我們先來(lái)回顧高階函數(shù)的定義:接收函數(shù)作為輸入,或者輸出另一個(gè)函數(shù)的一類函數(shù),被稱作高階函數(shù)。對(duì)于高階組件,它描述的便是接受React組件作為輸入,輸出...
摘要:父組件向子組件之間非常常見(jiàn),通過(guò)機(jī)制傳遞即可。我們應(yīng)該聽(tīng)說(shuō)過(guò)高階函數(shù),這種函數(shù)接受函數(shù)作為輸入,或者是輸出一個(gè)函數(shù),比如以及等函數(shù)。在傳遞數(shù)據(jù)的時(shí)候,我們可以用進(jìn)一步提高性能。 本文主要談自己在react學(xué)習(xí)的過(guò)程中總結(jié)出來(lái)的一些經(jīng)驗(yàn)和資源,內(nèi)容邏輯參考了深入react技術(shù)棧一書(shū)以及網(wǎng)上的諸多資源,但也并非完全照抄,代碼基本都是自己實(shí)踐,主要為平時(shí)個(gè)人學(xué)習(xí)做一個(gè)總結(jié)和參考。 本文的關(guān)鍵...
摘要:父組件向子組件之間非常常見(jiàn),通過(guò)機(jī)制傳遞即可。我們應(yīng)該聽(tīng)說(shuō)過(guò)高階函數(shù),這種函數(shù)接受函數(shù)作為輸入,或者是輸出一個(gè)函數(shù),比如以及等函數(shù)。在傳遞數(shù)據(jù)的時(shí)候,我們可以用進(jìn)一步提高性能。 本文主要談自己在react學(xué)習(xí)的過(guò)程中總結(jié)出來(lái)的一些經(jīng)驗(yàn)和資源,內(nèi)容邏輯參考了深入react技術(shù)棧一書(shū)以及網(wǎng)上的諸多資源,但也并非完全照抄,代碼基本都是自己實(shí)踐,主要為平時(shí)個(gè)人學(xué)習(xí)做一個(gè)總結(jié)和參考。 本文的關(guān)鍵...
閱讀 3896·2021-11-24 09:39
閱讀 3734·2019-08-30 15:56
閱讀 1514·2019-08-30 15:55
閱讀 1179·2019-08-30 15:53
閱讀 2088·2019-08-29 18:37
閱讀 3755·2019-08-29 18:32
閱讀 3273·2019-08-29 16:30
閱讀 3185·2019-08-29 15:14