浅入Redux分享

组内的Redux分享

浅入Redux分享

业务背景

1.当很早以前完成的页面有新的需求时,需要花额外的时间去理清其中的数据处理含义。
2.当一个页面工作量较大,组件较多,数据流动较复杂的时候,没有一目了然的处理方式。

对于Redux的个人理解

  1. 单一状态树:即对象。
  2. 声明式改变:打包对状态的一系列操作,并对其分类
  3. 可监听的变化

Redux 3个核心概念

下面就以一个简单的todoList为例,介绍有关Redux的三个概念

State

状态树,Object

State就是一个页面的状态

对于这个todoList所谓state就是:

  1. 所有的任务 ;
  2. 当前显示的任务种类(比如:已完成的,未完成的,全部);
  3. 每个任务的具体信息;

这个对象就长下面这样:

1
2
3
4
5
6
7
8
9
10
{
todos: [{
text: '整理Freemamba文档',
completed: true
}, {
text: '优化Freemamba build过程',
completed: false
}],
visibilityFilter: 'SHOW_COMPLETED'
}

Action

行为,Object

一个描述操作的对象

对于这个todoList所谓的action就是:

  1. 添加一个名为…的任务
  2. 完成指定任务
  3. 切换当前页面显示任务的种类

下面是对应的3个action

1
2
3
{ type: 'ADD_TODO', text: '实现组件嵌套' }
{ type: 'COMPLETE_TODO', index: 0 }
{ type: 'SET_FILTER', filter: 'SHOW_ALL' }

Reducer

定义action如何生成新的state,Function

一个函数,获取当前State,和Action,生成新State

1
2
3
4
5
6
7
8
9
10
11
function reducer(state, action){
switch(action.type){
case 'ADD_TODO':
return {...};
case 'COMPLETE_TODO':
return {...};
case 'SET_FILTER':
return {...};
default: return state;
}
}

基本使用

1. 创建一个store

通过传入reducer创建store

定义reducer.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
var initialState = {
todos: [...],
visibilityFilter: 'SHOW_COMPLETED'
};
function addTodoReducer(state, action){
var todos = state.todos.concat({text: action.text, complete: false});
return Object.assign({}, state, {todos: todos});
}
....
function reducer(state, action){
if(action.type === void 0){
return initialState;
}
switch(action.type){
case 'ADD_TODO':
return addTodoReducer(state, action);
case 'COMPLETE_TODO':
return completeTodoReducer(state, action);
case 'SET_FILTER':
return setFilterReducer(state, action);
default: return state;
}
}
module.exports = reducer;

定义action

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function addTodo(text){
return { type: 'ADD_TODO', text: text };
}
function completeTodo(index){
return { type: 'COMPLETE_TODO' , index: index };
}
function setFilter(filterName){
return { type: 'SET_FILTER', filter: filterName };
}
module.exports = {
addTodo: addTodo,
completeTodo: completeTodo,
setFilter: setFilter
};

创建store

1
2
3
4
5
6
7
8
9
10
11
12
13
var Redux = require('redux');
var reducer = reuqire('./reducer.js');
var actions = require('./actions.js);
var store = Redux.createStore(reducer, {todos: []});
/*添加一个任务*/
store.dispatch(actions.addTodo('优化Freemamba Build过程'));
/*获取当前状态*/
store.getState();
/*监听State改变*/
store.subscribe(function(){});
/*替换Reducer*/
store.replaceReducer(reducer);

简单介绍基本的API

Redux.createStore

根据Reducer,preloadedState(可选,初始状态),enhancer(可选,函数)创建Store

Redux.combineReducers

针对状态树的每个属性,书写对应的Reducer

1
2
3
4
5
6
7
8
9
10
11
12
var reducer = Redux.combineReducers({
todos: function(todos, action){
if(todos === void 0){
return [];
}
switch(action.type){
case 'ADD_TODO':
return todos.concat({text: 'zxr', complete: false});
default: return todos;
}
}
});

Redux.applyMiddleware

包裹store._dispatch方法,创建中间件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var logger = function(store){
return function(next){
return function(action){
console.log('before dispatch', store.getState())
let returnValue = next(action);
console.log('after dispatch', store.getState());
return returnValue;
}
};
}
var store = Redux.createStore(reducer, Redux.applyMiddleware(logger));
store.$dispatch(....);
//'before dispatch {todos:[]}'
//'after dispatch {todos: [{text: 'zxr', complete: false}]}'

Redux.bindActionCreators

创建Action的时候,自动dispatch

动手实现一个简易的Redux

实现简单的Redux,创建一个store,获取状态,分发action,监听变化

Redux.createStore

Redux.createStore(reducer, preloadState)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
Redux.createStore = function(reducer, preloadState){
/*获取默认状态*/
var state = preloadState || reducer();
/*创建监听列表*/
var listener = [];
/*获取状态*/
var getState = function(){
return state;
};
/*分发action*/
var dispatch = function(action){
state = reducer(state, action);
setTimeout(function(){
_checkListeners();
}, 0);
};
/*订阅变化*/
var subscribe = function(listener){
listeners.push(listener);
};
/*执行监听器*/
var _checkListeners = function(){
listeners.forEach(function(item){item()});
};
return {
getState: getState,
dispatch: dispatch,
subscribe: subscribe
};
};

Redux.combineReducers

1
2
3
4
5
6
7
8
9
Redux.combineReducers = function(reducerMap){
return function(state, action){
var ret = {};
for(var key in reducerMap){
ret[key] = reducerMap[key](state || state[key], action);
}
return Object.assign({}, state, ret);
};
};

Redux.applyMiddleware

1
2
3
4
5
6
7
8
9
10
11
12
13
Redux.applyMiddleware = function(){
var middlewares = [].slice.call(arguments);
return function(store){
function getNext(index){
if(index>=middlewares.length){
return store._dispatch;
}
return middlewares[index](getNext(index+1))
}
return middlewares[0](getNext(1));
};
};
0%