以前在有道雲筆記上寫過一篇 Redux 學習實踐的文章,附帶了一個小 Demo。因爲一段時間沒看 Redux,加上以前缺少足夠的練習,如今想重構我的博客,使用 Redux 進行狀態。如今不得不回頭再看看 Redux 相關東西。這裏順便記錄下學習筆記,一來便於回顧,二來但願對他人有所幫助。筆記同步寫在我的博客網站java
這篇文章是知識點的梳理,若是你對 Redux 的基礎有必定了解,閱讀起來可能比較合適。react
Redux 能夠說是 Flux 架構思想的最佳實踐方案,用於對大型、複雜、多數據來源的 React 進行數據管理。遵循 Redux 的設計原則,再配合 React 容器組件、展現組件分離的代碼組織原則,可讓咱們的項目結構清晰,數據流清晰,十分利於項目的維護開發。git
關於這三大原則的深刻理解建議參考 《深刻React技術棧》、《深刻淺出React和Redux》github
有 MVC 框架使用經驗的同窗應該清楚,MVC 的工做過程是這樣:view 層將用戶行爲傳遞到 controller 中的action, controller 中的 action 和 Model 層交互操做數據,返回到 view。一般 MVC 框架的實現 M 和 V 層是能夠交互的,這樣數據就不是單向流動,這種設計不少場景下很靈活,寫起來很爽快,可是要項目過大,項目數據流複雜,項目維護就不爽了。redux
Redux 則嚴格遵循上面提到的設計三大原則,工做過程是這樣的:view 層觸發一個 action,這個 action 由 store.dispatch(action) 傳遞給 reducer,reducer 根據 previousState 和 action type 返回一個新的 state(不修改數據), 如此實現了數據的變動。數組
上面 Redux 的工做過程提到了 Redux 有 store、action、reducer 這些概念,這些都是 Redux 對外提供的核心 API,咱們來看看他們分別是幹嗎的。bash
store架構
store 做爲整個應用數據的惟一來源,用於保存數據和 dispatch action。store 使用 Redux 提供的 createStore 方法來生成。框架
import { createStore } from 'redux';
let store = createStore(reducer)
複製代碼
createStore 接受一個 reducer 做爲參數,返回一個 store 對象。store 對象包含 4 中方法:dom
getState():// 用於獲取 store 中當前的狀態
dispatch():// 用於分發 action,這個是改變 store 中數據的惟一方式
subscribe(listener):// 註冊一個監聽者,在 store 發生變化時被調用
replaceReducer(nextReducer):///更新當前 store 中的 reducer
複製代碼
reducer
reducer 本質上是一個函數,這個函數能接受一個 action 和一箇舊的狀態(previousState),根據 previousState 和 action 返回新的狀態
reducer(previousState, action) => newState
複製代碼
reducer 必須是一個純函數,不能修改原來狀態,關於純函數的概念請閱讀其餘資料學習。
action
reducer 的 action 本質上是一個 javaScript 對象,這個對象必須有一個 type 屬性,用來代表 action 的類型,還能夠有 payload, error, meta 屬性。關於 action 對象的屬性,社區有個規範,能夠參考github.com/redux-utili…
const action = {
type: 'ADD_TODO',
payload: 'todo'
}
複製代碼
reducer 就是根據 action type 屬性來決定返回新的 state。
我在學習 Redux 的時候,看了不少文檔,認爲對 Redux 的概念瞭然於胸,可是動手寫第一個小 Demo 的時候仍然以爲很難下手,多是 Redux 這些概念對我而言太新。這裏給出我寫的第一個小 Demo。
這個 Demo 實現了點擊按鈕讓數字加一減一的功能,沒有任何複雜度,單純的是爲了瞭解 action
、store
、reducer
的具體做用和協做關係。
Demo 地址: github.com/wewin11235/…
爲了便於觀察,Demo 的代碼都丟在了一個文件裏,在實際開發中,必定要遵循好的代碼組織原則。
import React from 'react';
import ReactDOM from 'react-dom';
// 建立 action
// action 是 javaScript 對象,是用戶行爲的抽象,必須包含一個 stype 字段
// 根據 Demo 須要實現記數功能,抽象出兩種 action, 一種表示加,一種表示減
const incream_action = { type: 'INCREAM' };
const decream_action = { type: 'DECREME' };
// 建立 reducer
// reducer 接受一個 previousState 和 action 返回一個新的 state
const reducer = (state=0, action) => {
switch (action.type) {
case incream_action.type:
return state + 1;
case decream_action.type:
return state - 1;
default:
console.log('default');
return state;
}
}
// 建立 store
// store 建立使用 createStore(reducers)
// createStore 由 redux 提供
import { createStore } from 'redux';
let store = createStore(reducer);
// 建立計數組件
class Counter extends React.Component {
constructor(props) {
super(props);
}
render() {
const { count, doIncrement, doDecrement } = this.props
return(
<div>
<span>{count}</span>
<button onClick={doIncrement}>+</button>
<button onClick={doDecrement}>-</button>
</div>
)
}
}
const render = () => ReactDOM.render(
<Counter
count={store.getState()}
doIncrement={() => store.dispatch(incream_action)}
doDecrement={() => store.dispatch(decream_action)}
/>,
document.getElementById('root')
);
render();
// 爲了能在 store 發生變化後能刷新頁面,須要給 store 註冊一個監聽事件
// store 變化後,刷新頁面
store.subscribe(render);
複製代碼
最小 Redux 應用誕生。
歡迎指正,補充!