狀態管理是當前前端框架開發當中一個很重要的點當業務或者系統複雜時,狀態管理能讓咱們更加清晰地瞭解數據的流動javascript
本文經過實現一個簡單的Redux來闡述一個狀態管理庫的思想前端
目前前端開發框架盛行,在框架的使用過程當中就會遇到一個問題:組件間的數據通訊如何來作。簡單是父子組件咱們能夠經過props
來實現數據通訊,當組件層級變深,僅靠props
就不足夠支撐咱們的需求,一個全局的狀態管理也就變爲一個迫切的需求。java
Redux只有一個Store,Store不能直接進行修改,每次操做以後都是返回一個新的對象數組
Action前端框架
Action就是View發出的通知,告訴Store 數據要改變,Action經過特定的type來知曉作何種操做閉包
const action = { type: 'plus', data: {} };
Reducer是一個純函數,接受action和state,而後返回一個新的state。框架
總結一下,Redux的流程以下:函數
// View 發出 Action store.dispatch(action); // store 自動調用 Reducer,而且傳入兩個參數:當前 State 和收到的 Action。 Reducer 會返回新的 State let nextState = xxxReducer(previousState, action); // State 一旦有變化,Store 就會調用監聽函數 store.subscribe(listener); // listener中能夠修改組件的狀態,從新渲染組件 function listerner() { let newState = store.getState(); component.setState(newState); }
狀態管理,說到底就是將須要共享的數據存放在一個公共的地方,全部組件都經過它來進行數據的操做。天然而然的,咱們能夠想到建立一個全局的對象來存放數據,因此先建立一個state.js
文件測試
// state.js export const state = { count: 0, }
有了數據,咱們就須要有數據的存取,以及發佈訂閱事件spa
所以有了如下的store.js
文件
// store.js import { state } from './state.js'; export const createStore = (reducer) => { let currentState = state; // state function getState() { // 獲取state return currentState; } function dispatch() { // 設置state } function subscribe() { // 訂閱事件 } return { getState, dispatch, subscribe }; }
在這裏其實用到了閉包的思想
其中getState
很簡單,就是獲取當前的state
值
狀態管理庫的一個原則是不能隨便修改狀態的值,須要作到有條理,有標記地修改。咱們將操做單獨封裝在reducer.js
中,以此來保持store.js
的純淨
// reducer.js import { state as initialState } from './state.js'; export function reducer(state = initialState, action) { switch(action.type) { case 'plus': return { ...state, count: state.count + 1 }; break; case 'subtract': return { ...state, count: state.count - 1 } break; default: return initialState; } }
而後在store.js
中進行使用
// store.js import { state } from './state.js'; export const createStore = (reducer) => { let currentState = state; // state function getState() { // 獲取state return currentState; } function dispatch(action) { // 設置state currentState = reducer(currentState, action); } function subscribe() { // 訂閱事件 } return { getState, dispatch, subscribe }; }
狀態管理庫的另外一個能力就是可以經過數據改變引發視圖的改變。咱們經過發佈訂閱模式,就能實現這一效果,經過subscribe()
來訂閱事件,在dispatch()
的時候觸發訂閱的消息。固然真正的狀態管理庫中這一塊確定是很複雜的,咱們這裏只是簡單地寫個示例。
咱們經過一個數組來存放監聽的事件,經過subscribe
來添加事件
// store.js import { state } from './state.js'; export const createStore = (reducer) => { let currentState = state; // state let queue = []; function getState() { // 獲取state return currentState; } function dispatch(action) { // 設置state currentState = reducer(currentState, action); queue.forEach(fn => { fn(); }) } function subscribe(fn) { // 訂閱事件 queue.push(fn); } return { getState, dispatch, subscribe }; }
以後添加測試用例來進行測試
import 'createStore' from './store'; const store = createStore(reducer); store.subscribe(() => { console.log('component 1') }); store.subscribe(() => { console.log('component 2') }); store.dispatch({ type: 'plus' }); store.dispatch({ type: 'plus' }); console.log(store.getState()); // component 1 // component 2 // component 1 // component 2 // { count: 2 }
這就是一個簡單的Redux
的思想。