React作為一套優(yōu)秀的前端框架,為我們提供了一套十分優(yōu)秀的頁面構建方法和思想。可是,React還只是一套視圖構建框架,在軟件設計模塊里面還只是MVC的View層,涉及數據模型時需要一些其他框架的輔助。其中,最著名的莫過于Redux了。既然是結合React使用Redux,那么前端大爺假設你已經使用過React框架,對React有一定的了解了,并且大概知道action, reducer, dispatch的關系,否則請先移步其他書籍文檔,因為無論如何15分鐘內不可能從不會走到學會跑。
-----------------------------------分割線 0 分鐘---------------------------------
先解釋原理
首先,React組件有state, props沒錯吧。state是內部的狀態(tài),props是父組件傳進來的屬性,state, props變化了要觸發(fā)react diff并且調用render方法更新組件,同意吧。好,就是這么簡單的react基本原理,告訴我們除了用戶交互導致內部state變化外,數據流是從父組件通過props流向子組件導致子組件更新。這就是React的單向數據流:
自頂向下單向數據流!
自頂向下單向數據流!
自頂向下單向數據流!
重要的事情說三遍。
假設我們的app入口是這樣的:
ReactDOM.render(
<App />
document.getElementById('root')
);
這個App也是一個React組件,它是我們的項目中居于最頂層的父組件。如果我們有某個組件,他能夠提供數據源,而又居于App之上,那么數據就可以源源不斷的從它往下流到App以及各級子孫節(jié)點上去。所以Redux給我們提供了Provider:
import { Provider } from 'react-redux'
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
);
-----------------------------------分割線 5 分鐘---------------------------------
Provider接受一個屬性store,這就是我們全局的數據store。我們要根據reducer函數來創(chuàng)建它。
import { createStore } from 'redux'
import { combineReducers } from 'redux'
//reducer函數接受兩個參數,state和action,state帶默認的初始值
function reducer1(state = [], action) {
switch(action.type) {
case 'add':
return [...state, 'apple is very delicious']; // 這里一定要返回一個新的數組,而不能寫成state.push('apple is very delicious1');
default :
return state;
}
}
//reducer當然可以定義多個,不同的reducer對應著不同的state對象,上面的reducer1操作一個數組對象,這個reducer2操作一個Number類型state
function reducer2(state = 0, action) {
switch(action.type) {
case 'increase' :
++state;
return state;
default:
return state;
}
}
const reducer = combineReducers({
reducer1,
reducer2
})
var store = createStore(reducer);
store生成了,隨時可以通過store.getState()獲得當前store的值。初始狀態(tài)下調用getState()獲得的返回值是
{reducer1: [], reducer2: 0}。
看,reducer函數的名字對應著store里面state的名字。
為了幫助初學者學習,可以添加以下語句,監(jiān)聽每一次dispatch操作后store的狀態(tài):
store.subscribe(()=>{
console.log(store.getState());
})
-----------------------------------分割線 10 分鐘---------------------------------
現(xiàn)在我們有了最高級別的Provider,并定義好了reducers, 傳入了store。接下來我們該考慮子組件了。子組件長什么樣,要靠父組件給的props決定,可是數據都在最高級別的provider store里面,怎么樣把store里面的數據拿出來作為props給子組件呢?。。??
react-redux給我們提供了魔法黑科技:mapStateToProps和mapDispatchToProps。
顧名思義,把state和dispatch從store里面拿出來,作為props傳給子組件!
const mapStateToProps = state => {
return {
state1: state.reducer1
}
}
const mapDispatchToProps = dispatch => {
return {
add: () => {
dispatch({
type:'add'
})
}
}
}
class AppView extends Component {
render() {
const list = this.props.state1.map(v=>{
return (<p className="App-intro">{v}</p>)
})
return (
<div className="App">
<p>{list.length}</p>
{
list
}
<button onClick={()=>this.props.add()}>add</button>
</div>
);
}
}
const App = connect(
mapStateToProps,
mapDispatchToProps
)(AppView)
export default App;
看到了嗎,經過mapStateToProps和mapDispatchToProps處理后,我們直接在子組件AppView里面使用this.props.state1就可以拿到store里面的數據,直接使用this.props.add就可以dispatch相應的action。store變化后視圖的更新是自動的,無需手工干預。
源代碼見:https://github.com/myairforce1/simpleReduxDemo
看到這你是不是對在React中使用Redux有點感覺了呢?請原諒本文使用了一個極為簡陋的例子。本著老少咸宜,童叟無欺的初衷,我盡量搬上來一個功能少,但是好理解的例子。如果的確幫助到您,請留下您對本文的喜愛。