-
Redux
-
React-redux
-
React-router
Redux
1、基本用法:
-
Redux中存在幾個(gè)概念:state, action, dispatch
state: 依舊是組件的內(nèi)部的狀態(tài)
action: 組件動(dòng)作,相應(yīng)的改變組件內(nèi)部的狀態(tài)值
dispatch: 發(fā)出相應(yīng)的動(dòng)作Redux中提供createStore方法用于生成一個(gè)store對(duì)象,這個(gè)函數(shù)接受一個(gè)初始值state值和一個(gè)reducer函數(shù)。當(dāng)用戶(hù)發(fā)出相應(yīng)的action時(shí),利用傳入的reducer函數(shù)計(jì)算出一個(gè)新的state值,并返回。
使用Redux,我們只獲取一次數(shù)據(jù)并將其存儲(chǔ)在一個(gè)中心位置,稱(chēng)為 store。然后,任何組件都可以隨時(shí)使用這些數(shù)據(jù)。這就像附近有一家超市,我們的廚師可以在那里買(mǎi)到所有的食材。這家超市派卡車(chē)從農(nóng)場(chǎng)大批運(yùn)回蔬菜和肉類(lèi)。這比讓個(gè)別廚師親自去農(nóng)場(chǎng)效率高得多。
store 還是唯一的數(shù)據(jù)源。組件通常從 store 中獲取數(shù)據(jù),而不是其他地方。這使得 UI 保持高度統(tǒng)一。
store對(duì)象中包括getState方法(獲取目前的state),subscribe方法(指定監(jiān)聽(tīng)函數(shù),當(dāng)state變化時(shí)調(diào)用),dispatch方法(分發(fā)action)。
在使用過(guò)程中,需要將store作為參數(shù)傳遞給子組件。
// reducer
function counter(state = 0, action) {
switch (action.type) {
case 'ADD':
return state + 1;
case 'SUB':
return state - 1;
default:
return 10;
}
}
// 創(chuàng)建Store
let store = createStore(counter);
console.log(store.getState()); // 10
// 監(jiān)聽(tīng)器
function listener() {
console.log(store.getState()) // 先輸出11,在輸出10
}
// 訂閱事件監(jiān)聽(tīng)
store.subscribe(listener);
// 分發(fā)事件
store.dispatch({ type: 'ADD' });
store.dispatch({ type: 'SUB' });
-
多個(gè)reducer
當(dāng)存在多個(gè)reducer,分別管理不同方面的state,需要將其合并成一個(gè)reducer,redux中提供了combineReducers函數(shù),完成該項(xiàng)功能。
combineReducers({ reducer1,reducer2 }) //返回合并后的reducer
2、redux的不足:
-
陡峭的學(xué)習(xí)曲線(xiàn)
Redux 的學(xué)習(xí)曲線(xiàn)比較陡峭。 理解,記憶并習(xí)慣其模式需要時(shí)間。 如果你完全不會(huì) Redux 和 React ,不推薦你兩者同時(shí)學(xué)習(xí)。
-
“樣板” 代碼
在許多情況下,使用Redux意味著編寫(xiě)更多代碼。通常需要接觸多個(gè)文件才能使一個(gè)簡(jiǎn)單的功能正常工作。人們一直在抱怨他們必須用 Redux 編寫(xiě)的樣板代碼。
我知道,這聽(tīng)起來(lái)很矛盾。 我不是說(shuō) Redux 能夠用最少的代碼實(shí)現(xiàn)功能嗎? 這有點(diǎn)像使用洗碗機(jī)。 首先,你得花時(shí)間仔細(xì)地排列盤(pán)子。 在此之前,你將看到洗碗機(jī)的好處:節(jié)省實(shí)際清潔餐具的時(shí)間,消毒餐具等。你必須決定準(zhǔn)備時(shí)間是否值得。
-
性能損耗
由于其強(qiáng)制執(zhí)行的限制,Redux 也可能對(duì)性能產(chǎn)生影響。 每當(dāng)數(shù)據(jù)發(fā)生變化時(shí),它會(huì)增加一點(diǎn)開(kāi)銷(xiāo)。 在大多數(shù)情況下,這不是什么大問(wèn)題,而且放緩并不明顯。 仍然,當(dāng)存儲(chǔ)中存在大量數(shù)據(jù)并且當(dāng)數(shù)據(jù)頻繁改變時(shí)(例如,當(dāng)用戶(hù)在移動(dòng)設(shè)備上快速鍵入時(shí)),UI 可能因此變得緩慢。
3、Redux 不只是為 React 而生
一個(gè)常見(jiàn)的誤解是 Redux 僅用于 React。 聽(tīng)起來(lái)Redux在沒(méi)有React的情況下無(wú)法做任何事情。 事實(shí)上,正如我們之前所討論的,Redux在幾個(gè)重要方面補(bǔ)充了React。 React 是最最常見(jiàn)的 Redux 用例。
然而,事實(shí)上,Redux可以使用任何前端框架,如Angular、Ember.js 甚至jQuery 或者 普通的JavaScript。試著谷歌一下,你會(huì)發(fā)現(xiàn)這個(gè),這個(gè),這個(gè)甚至這個(gè)。Redux 的一般思想適用于任何地方
只要你明智地使用 Redux,你可以在很多情況下得到它的好處,而不僅僅是在React應(yīng)用中。
react-redux
- react-redux是為了方便開(kāi)發(fā),提供了一個(gè)Provider組件,以及connect方法。Provider組件作為做上層組件,需要將store作為參數(shù)注入組件中,此后在子組件中都可以訪問(wèn)到store這個(gè)對(duì)象;connect方法接受兩個(gè)參數(shù):mapStateToProps,actionCreators,并返回處理后的組件,其中mapStateToProps可以將對(duì)應(yīng)的state作為prop注入對(duì)應(yīng)的子組件,actionCreator可以將對(duì)應(yīng)的actioncreator作為prop注入對(duì)應(yīng)的子組件。
// 定義Connect,將對(duì)應(yīng)的數(shù)據(jù)注入
const mapStateToProps = (state) => {
return { num: state }// 必須返回一個(gè)對(duì)象
};
const actionCreator = { addAction, subAction, addActionAsync }
App = connect(mapStateToProps, actionCreator)(App)
- 裝飾器寫(xiě)法:
@connect(
(state) => ({ num: state.counter }),
{ addAction, subAction, addActionAsync }
)
- 使用上述寫(xiě)法,需要安裝babel插件babel-plugin-transform-decorators-legacy,并且在babelrc中添加相應(yīng)的配置
npm install --save-dev babel-plugin-transform-decorators-legacy
"plugins": [
"transform-decorators-legacy"
]
React-router
- react-router提供了web和Native兩個(gè)版本,當(dāng)在瀏覽器中使用時(shí),需要安裝react-router-dom
npm install --save react-router-dom
-
react-router-dom中提供了BrowserRouter, Link, Route, Switch,Redirect。
其中:
1、 BrowserRouter包裹所有需要路由控制的內(nèi)容,在使用redux時(shí),需要放置在Provider組件中;
2、 Link組件用于鏈接某個(gè)路徑下,用戶(hù)點(diǎn)擊跳轉(zhuǎn);
3、 Route組件用于路由到這個(gè)組件;
4、Switch組件用于在內(nèi)部Route組件中選一個(gè);
5、 Redirect組件用于重定向到某個(gè)路徑下;
<Provider store={store}>
<BrowserRouter>
<Switch>
<Route path="/" exact component={Dashboard}></Route>
<Route path="/login" component={Auto}></Route>
<Route path="/dashboard" component={Dashboard}></Route>
<!-- <Redirect to="/dashboard"></Redirect> -->
<!-- <Link to="/dashboard"></Link> -->
</Switch>
</BrowserRouter>
</Provider>