由Flux演變而來,做爲狀態容器,提供可預測的狀態管理。html
複雜應用中沒法獲取操做記錄,而狀態的改變每每意味着對應視圖的變化,這一過程是不可控的。前端
提供一種機制,統一對狀態的查詢、改變、應用
進行管理,同時對每一次的狀態變動可進行回溯追蹤
。vue
多個組件件間可能存在數據的共享以及通訊。react
這裏能夠簡單將其理解爲充當了eventBus的角色。git
視圖的改變以及數據的獲取等操做雜糅在一塊兒,不利於維護github
從具體操做
-> 狀態變動
-> 觸發視圖更新
,這一單向數據流
的控制,不只使得對狀態變化的過程變得可控,同時解耦了數據M和視圖V
。見下圖,針對相同的action,其數據流轉以及state管理是獨立於前端模板的,所以能夠實現跨框架的複用。 web
Redux主要有以下幾個概念:vuex
action:通常寫法:<type:操做意圖(通常定義爲字符串常量), payload:{text:"要改變的新數據"}>
,是store數據的惟一來源。redux
store:Redux應用只有一個單一的store。當須要拆分數據處理邏輯時,你應該使用 reducer 組合而不是建立多個store。(經常使用方法:dispatch
、getState
、subscribe
等)緩存
state:數據對象,由store對象管理,經過getStore()只讀
。
改變的惟一途徑:由store的dispatch方法對action進行分發,reducer進行處理 範式化。
reducer:對action作出相應響應,返回新生成的state(這也是保證可回溯的緣由)。 新生成state有以下幾種方式:
Object.assign({}, oldState, newState)
{...oldSate, 新值}
Immutable
中間件
這裏強調下Redux的中間件使用,在每次action觸發時,都會先經過層層中間件再真正執行。這個過程賦予了咱們諸如日誌記錄等能力。洋蔥圈模型,和KOA的中間件原理相似。
運做原理圖以下:
如下是仿Redux寫的demo,實現了Redux的基本能力,緩存了操做記錄,進一步擴展能夠實現諸如回退等功能。
如下列出了幾個核心函數:
store
/**
* store提供的方法:
* 1. getState:獲取當前state
* 2. dispatch:觸發行爲
* 3. subscribe:訂閱事件
*/
function createStore(reducers, initState) {
//historyState可用做時光機
let state = initState, historyState = [{action:'init', state: initState}], listeners = [];
let getState = () => state;
let subscribe = (event) => {
listeners.push(event);
/**
* 註冊事件的同時,獲取事件句柄
* let fnHandle = fnsubscribe(fn)
* 刪除對應註冊事件
* fnHandle();
* */
return () => {
listeners = listeners.filter(eventItem => eventItem != event);
}
}
let dispatch = (action) => {
//reducer根據action對state作改變,返回全新的state
state = reducers(state, action);
historyState.push({action, state})
//state改變的狀況下,觸發事件
listeners.forEach(listener => listener());
}
return {
dispatch,
getState,
subscribe,
getHistoryState: () => historyState
}
}
複製代碼
綁定中間件applyMiddleware
//將中間件綁定到
let applyMiddleware = middlewares => (createStore) => (...args) => {
let store = createStore(...args);
let dispatch = store.dispatch;
let params = {
dispatch,
getState: store.getState
};
middlewares = middlewares.map(mw => mw(params));
//組合中間件,加強dispatch
//裝飾者模式 & 洋蔥圈,compose對中間件的組合
dispatch = compose(middlewares)(dispatch);
//返回加強後的dispatch
return Object.assign(store, {dispatch});
}
複製代碼
使用
/**
* 對action作處理,返回全新的state
*/
function reducers(state, action){
switch(action){
case 'add':
return state += 1;
case 'minus':
return state -=1;
default:
return 0;
}
}
複製代碼
/**
* 中間件(注意中間件的約定格式)
*/
function middleware1({dispatch, getState}) {
return function(next) {
return function(action) {
console.log(`【日誌】當前state值:${getState()},執行${action}`);
next(action);
console.log(`【日誌】操做完成後,state值:${getState()}`);
}
}
}
function middleware2({dispatch, getState}) {
return function(next) {
return function(action) {
console.log(`>>>>>>>>>>>>>>>>>>`);
next(action);
console.log(`<<<<<<<<<<<<<<<<<<`);
}
}
}
複製代碼
/**
* 對外暴露:
* 1. createStore: 產生store
* 2. applyMiddleware:中間件處理
*/
let initState = 1;
let store = applyMiddleware([middleware2, middleware1])(createStore)(reducers, initState);
複製代碼
demo展現效果以下:
這裏只是簡單說明redux的能力,具體功能可自行擴展。
完整代碼見:github.com/269117220/w…