參考redux倉庫的src目錄,初步手寫實現了以下3個方法
- createStore() : 創建數據倉庫,導出了3個方法(dispacth,subscribe,getState)
- combineReducers():合併多個小的reducer,傳入一個對象
- bindActionCreators() : 簡化代碼 api,把所有的action存入一個對象,和dispacth,一塊傳入此方法中 就不用再到處手動調用
dispatch
了
還剩下幾個,先不說了,然而,就這麼幾行代碼,已經基本讓項目配合這些代碼跑起來一個數據倉庫了,然而,它還是有很多的冗餘代碼,比如在 react 項目中,還是需要每個文件 引入好多額外的redux 的東西, 所以,開發中還會結合 react-redux
一塊使用,這樣就只操作 props
了, 也是開發者比較熟悉的 react 的語法,關於 react-redux
的實現,參考倉庫源碼,發現,它就是使用了 react 的 context 這個api,實現的自上而下的跨組件通信
參考文檔context一節
使用context幾個步驟
- 創建上下文對象,導出一個對象,該對象又導出倆組件
// createContext() 接收一個參數,作爲默認狀態值
const Context = React.createContext(null);
// 提供倆組件
let { Provider, Consumer } = Context;
- 使用上下文對象導出的組件
Provider
: 提供者,默認頂級父組件, 有一個默認寫死的屬性value
,並且只能通過value
屬性向下傳值Consumer
: 消費者, 用於子組件從父組件取值
- 父組件, 提供數據,供子組件消費
// ... 略
class App extends Component {
render() {
let value = 'hello';
return (
<Provider value={value}>
<div style={{ border: '2px solid #950', padding: 5 }}>
<p>我是父組件的默認值:{value}</p>
<AChild />
<CChild />
<BChild />
</div>
</Provider>
);
}
}
- 子組件獲取父組件向下傳的的數據,
class AChild extends Component {
render() {
return (
<Consumer>
{(value) => (
<div style={{ border: '3px solid #400', margin: 5 }}>
<p>我是(類組件)子組件A</p>
<span>我接收的值:{value}</span>
</div>
)}
</Consumer>
);
}
}
- 類組件還可以使用
this.context()
語法獲取
// 子組件3(類組件)
class CChild extends Component {
static contextType = Context;
render() {
return (
<div style={{ border: '2px solid #200', margin: 5 }}>
<p>我是(類組件)子組件C</p>
<span>我接收的值:{this.context}</span>
</div>
);
}
}
- 函數組件只能使用
Consumer
獲取數據
function BChild() {
return (
<Consumer>
{(value) => {
return (
<div style={{ border: '2px solid #f90', margin: 5 }}>
<p>我是(函數組件)子組件B</p>
<span>我接收的值:{value}</span>
</div>
);
}}
</Consumer>
);
}