由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…