公司的項(xiàng)目使用的是react+redux+antd的技術(shù),作為新手我在不斷學(xué)習(xí),整理一下react+redux的內(nèi)容,作為項(xiàng)目入門的記錄。
網(wǎng)上有很多有趣清晰的說明文章,參考了幾篇列一下:
https://zhuanlan.zhihu.com/p/20641377?columnSlug=haochuan
https://github.com/jasonslyvia/a-cartoon-intro-to-redux-cn
http://www.ruanyifeng.com/blog/2015/03/react.html(阮大神的文章需要好好學(xué)習(xí)下的)
http://www.runoob.com/react/react-state.html?
下面是關(guān)于react和redux的學(xué)習(xí)內(nèi)容摘要
react:
特點(diǎn):
1.組件化——JSX語法;
2.單向數(shù)據(jù)流------數(shù)據(jù)一旦更新,就將重新渲染整個APP---redux;
3.虛擬DOM樹———更新時重建DOM樹,找到與上一個版本的DOM差異,計算最新DOM更新操作,批量進(jìn)行更新----可以直接渲染特定的頁面而不是整個APP;
React 把組件看成是一個狀態(tài)機(jī)(State Machines)。通過與用戶的交互,實(shí)現(xiàn)不同狀態(tài),然后渲染 UI,讓用戶界面和數(shù)據(jù)保持一致。這個渲染過程為:交互—>狀態(tài)改變—>實(shí)現(xiàn)不同狀態(tài)—>渲染UI。React 里,只需更新組件的 state,然后根據(jù)新的 state 重新渲染用戶界面(不要操作 DOM)。
舉個例子。最近做的一個小需求,通過訂單的狀態(tài)更改訂單的類型列表,出了bug,后來在前輩指導(dǎo)下修正了。貼一部分代碼說明一下:
handleOrderTypeChange= (value) => {
? ? this.setState({orderType: value});
? ? this.props.form.setFieldsValue({order_status: orderTypeToStatus[value] ?orderTypeToStatus[value][0] : orderStatus[0].name});
}
//在view中進(jìn)行更新
render{ ……
? ? {getFieldDecorator('order_type',{initialValue:"",onChange:this.handleOrderTypeChange}) ? ? ? ? ?(
? ? ? ? {this.orderOptions()}
? ? )}
}
這部分通過在函數(shù) handleOrderTypeChange 中,使用this.setState 方法修改狀態(tài)值,然后使用antd的方法 setFieldsValue,將ordertype的內(nèi)容推進(jìn)文本框即可。這個例子體現(xiàn)了react的組件化的特點(diǎn)。
redux:
從上述對react的特點(diǎn)介紹,可以看出,
1. react的數(shù)據(jù)是單向流動的,沒有數(shù)據(jù)向上回溯的能力,也就是說數(shù)據(jù)只能單向向下分發(fā),或者自行內(nèi)部消化。
2. react根本無法讓兩個組件相互交流,互相使用數(shù)據(jù),然后這時候不通過DOM溝通(也就是React體制內(nèi))解決的唯一辦法就是提升state,將state放到共有的父組件中來管理,再作為props分發(fā)回子組件。
3. 子組件改變父組件state的辦法只能是通過onClick觸發(fā)父組件聲明好的回調(diào),也就是父組件提前聲明好函數(shù)或方法作為契約描述自己的state將如何變化,再將它同樣作為屬性交給子組件使用。
4. 為了面臨所有可能的擴(kuò)展問題,最容易想到的辦法就是把所有state集中放到所有組件頂層,然后分發(fā)給所有組件。
為了有更好的state管理,就需要一個庫來作為更專業(yè)的頂層state分發(fā)給所有React應(yīng)用,這就是Redux。
讓我們回來看看重現(xiàn)上面結(jié)構(gòu)的需求:
a. 需要回調(diào)通知state (等同于回調(diào)參數(shù)) -> action
b. 需要根據(jù)回調(diào)處理 (等同于父級方法) -> reducer
c. 需要state (等同于總狀態(tài)) -> store
因此,redux的三要素就是 action,reducer,store:
action:純聲明式的數(shù)據(jù)結(jié)構(gòu),只提供事件的所有要素,不提供邏輯。
reducer:一個匹配函數(shù),action的發(fā)送是全局的:所有的reducer都可以捕捉到并匹配(比如使用switch...case結(jié)構(gòu))與自己相關(guān)與否,相關(guān)就拿走action中的要素進(jìn)行邏輯處理,修改store中的狀態(tài),不相關(guān)就不對state做處理原樣返回。
store:負(fù)責(zé)存儲狀態(tài)并可以被react api回調(diào),發(fā)布action.
具體工作的時候,流程為:
通過view(state)觸發(fā)action,通過reducer匹配action,通過在reducer中改變state,最終反應(yīng)到view中;
流程圖為:
view ---> action ---> reducer ---> store(state) ---> view
當(dāng)然一般不會直接把兩個庫拿來用,還有一個binding叫react-redux, 提供一個Provider和connect。
Provider是一個普通組件,可以作為頂層app的分發(fā)點(diǎn),它只需要store屬性就可以了。它會將state分發(fā)給所有被connect的組件,不管它在哪里,被嵌套多少層。
connect是真正的重點(diǎn),它是一個柯里化函數(shù),意思是先接受兩個參數(shù)(數(shù)據(jù)綁定mapStateToProps和事件綁定mapDispatchToProps),再接受一個參數(shù)(將要綁定的組件本身):
mapStateToProps:構(gòu)建好Redux系統(tǒng)的時候,它會被自動初始化,但是你的React組件并不知道它的存在,因此你需要分揀出你需要的Redux狀態(tài),所以你需要綁定一個函數(shù),它的參數(shù)是state,簡單返回你關(guān)心的幾個值。
mapDispatchToProps:聲明好的action作為回調(diào),也可以被注入到組件里,就是通過這個函數(shù),它的參數(shù)是dispatch,通過redux的輔助方法bindActionCreator綁定所有action以及參數(shù)的dispatch,就可以作為屬性在組件里面作為函數(shù)簡單使用了,不需要手動dispatch。這個mapDispatchToProps是可選的,如果不傳這個參數(shù)redux會簡單把dispatch作為屬性注入給組件,可以手動當(dāng)做store.dispatch使用。這也是為什么要科里化的原因。
做好以上流程Redux和React就可以工作了。簡單地說就是:
1.頂層分發(fā)狀態(tài),讓React組件被動地渲染。
2.監(jiān)聽事件,事件有權(quán)利回到所有狀態(tài)頂層影響狀態(tài)。
最基礎(chǔ)的一點(diǎn)探索,未完待續(xù)。。