組合所有的東西,有容乃大
在前面一個(gè)章節(jié)里,我們已經(jīng)做了一個(gè)事例如何重用組建,現(xiàn)在要學(xué)會(huì)是這些組建高效聯(lián)系起來,React如此強(qiáng)大的原因是能過讓你以小的、可測(cè)試的、方便維護(hù)的組建以搭積木的方式構(gòu)建出復(fù)雜的應(yīng)用,運(yùn)用這種方式你能夠完全掌控每一個(gè)部分,
在這個(gè)章節(jié)里,我們將會(huì)通過最受歡迎的組合模式和工具,以下是這節(jié)的要點(diǎn)
-組建之間的聯(lián)系通過props 和 children
-容器/展示模式如何使得代碼更易維護(hù)
-mixins這種方式來處理問題和為什么它失敗了
-什么是高階組建以及怎樣用它來更好構(gòu)建應(yīng)用
-recompose 庫和他的ready-made函數(shù)
-如何與上下文交互以及避免耦合我們的組建
-子組建模式的功能是什么以及它有哪些好處
容器/展示模式如何使得代碼更易維護(hù)
這種模式,每個(gè)組建分離成兩個(gè)精簡的部分,每個(gè)部分各司其職,容器這部分負(fù)責(zé)組建的邏輯和API調(diào)用、數(shù)據(jù)處理、事件處理,展示這部分定義用戶界面,接收容器的props,輕邏輯,適合用無狀態(tài)的組建,沒有規(guī)定說展示組建不需要有狀態(tài),例如,它還保持UI的狀態(tài)在內(nèi)部
《例子已經(jīng)做完》》》》》
Mixins
組建的可重性很好,但是如果不同的組建在許多地方只需要同樣的行為,應(yīng)該如何做呢?
我們不想要重復(fù)的擼代碼,幸好React提供一個(gè)工具Mixins,當(dāng)我們需要這種功能的時(shí)候在不同組建里,
雖然現(xiàn)在已經(jīng)棄用了Mixins,但是值得我們?nèi)ニ伎既绾谓鉀Q這類問題,
高階組建
上節(jié)講了,用Mixins來處理通用的功能,和它帶來的問題,
在第二章有提到過高階函數(shù),這種函數(shù)賦予函數(shù)新的行為并且會(huì)返回一個(gè)新的組建,下面我們就用它來處理通用的功能,并且處理掉Mixins帶來的缺點(diǎn),
高階組建是一個(gè)函數(shù),以組建作為參數(shù),返回一個(gè)功能增強(qiáng)的組建,接下來是一個(gè)使用高階組建的例子,為每一個(gè)組建加上className
const withClassName = Component => props =>
<Component {...props} ?className="my-class" />
初看起來,很難理解,聲明一個(gè)withClassName函數(shù),以Component作為參數(shù),返回一個(gè)新函數(shù),這個(gè)新的函數(shù)是無狀態(tài)的組建,這個(gè)組建呢,接收props,渲染接收參數(shù)Component
《例子已經(jīng)完成》
Recompose
高階組建庫,提供小工具封裝組建的一些邏輯,傻瓜式和可重用操作組建,
假設(shè)你的組建接收一個(gè)用戶對(duì)象從API,對(duì)象里面有很多的屬性,讓組建隨意的接收對(duì)象不是好的方式,因?yàn)闀?huì)依賴對(duì)象的模型,一旦對(duì)象改變了,組建將變的不可用,好的方式是讓組建從父組建接收原始的定義好的單個(gè)Props,
const Profile = ({ name, age }) => (
? ? <div>Name: {name}</div>
? ? ?<div>Age: {age}</div>
)
Profile.propTypes = {??
? ? ? ? ? ?name: React.PropTypes.string,??
? ? ? ? ? ?age: React.PropTypes.number,?
}
Context
高階組建能輕松的處理context
在某些情況下,使用context非常有用,通過它傳遞信息給子組建而不是使用props,但是,在某些情況下,我們不想通過父組件的props屬性一級(jí)一級(jí)的往下傳遞,我們希望在某一級(jí)子組件中,直接得到上N級(jí)父組件中props中的值,如何利用React中的Context來進(jìn)行值的越級(jí)傳遞
Function as Child
const Name = ({ children }) => children('World')
Name.propTypes = {? children: React.PropTypes.func.isRequired, }?
<NAME>
? ? ? ?{name => <div>Hello, {name}!</div>}
</NAME>
hello,World!