首页 > IT职业 > IT图书 > JavaScript 的状态容器 Redux
JavasSript 的状态容器
跟 React 没有关系,Redux 支持 React、Angular、Ember、JQuery 甚至 JavaScript。

Redux
单一数据源
State 是可读的
使用纯函数来执行
记录了用户行为的数据的载体
Action 是 Store 数据的唯一来源
Action 是一个 JavaScript 对象
Action 内有一个 Type 字段
Action 通常被定义为字符串常量
尽量减少在 Action 中传递的数据
var actionAddTodo = { type: 'ADD_TODO', text: '吃饭'};var actionCompleteTodo = { type:'COMPLETE_TODO', index:2};var actionSelectFilter = { type:'SETFILTER', filter:'SHOW_ALL'};
// 创建对象的工厂模式function createAction(text){ var o = new Object();
o.type = ADD_TODO;
o.text = text; return o;
}function addTodo(text){ return { type: 'ADD_TODO',
text
}
}
存放程序数据的一颗 ,或者说是一个数据库。
State 是只读的,可能是一个 JavaScript 对象、数组、Immutable.js 的数据结构
唯一能更新 State 的方法就是触发 Action ,使用 Store 的 Dispatch 更新 State 。
单一数据源,State 是程序的唯一数据源
确保视图和网络请求只能表现出我想要修改 State , 然后通过触发 Action 修改
只有唯一更新 State 方法,我们可以更容易的实现撤销 / 重做这类应用
Todo 的任务列表
var initState = { filter: 'SHOW_ALL', todos: []
}
应该尽量是 State 可以轻松的转化为 JSON
尽可能把 State 规范化,不存在嵌套
把所有数据都放到一个对象里,每个数据以 ID 作为主键
把 State 想象成一个数据库
//方式一[{ id: 1, title: 'Some Article', author: { id: 1, name: 'Dan'
}
}, { id: 2, title: 'Other Article', author: { id: 1, name: 'Dan'
}
}]//方式二{ result: [1, 2], entities: { articles: { 1: { id: 1, title: 'Some Article', author: 1
}, 2: { id: 2, title: 'Other Article', author: 1
}
}, users: { 1: { id: 1, name: 'Dan'
}
}
}
}
把所有的源对象属性复制到目标对象并放回。
// 用法一var o1 = {a:1};var o2 = {b:2};var o3 = {c:3};var obj1 = Object.assign(o1,o2,o3);console.log(o1); // {a:1,b:2,c:3}console.log(obj1); // {a:1,b:2,c:3}// 用法二var o4 = {a:1,b:2};var o5 = {b:3,c:4};var obj2 = Object.assign({},o4,o5);console.log(obj2); // {a:1,b:2,c:3,d:4}
必须保证 Reducer 是一个纯函数,我们不能改变传入的 State,所以我们需要使用 Object.assign({},state)复制一个 State
var state = {filter:'SHOW_ALL',todos:['x1','x2']};var obj3 = Object.assign({},state,{todos:[state.todos[1],'x3']})console.log(obj3)
var createStore = Redux.createStore;var combineReducers = Redux.combineReducers;var applyMiddleware = Redux.applyMiddleware;const ADD_TODO = 'ADD_TODO';const COMPLETE_TODO = 'COMPLETE_TODO';const SETFILTER = 'SETFILTER';const FILTER = { SHOW_ALL: 'SHOW_ALL', SHOW_COMPLETE: 'SHOW_COMPLETE', SHOW_ACTIVE: 'SHOW_ACTIVE'}function addTodo(text){ return { type: ADD_TODO,
text
}
}function completeTodo(index){ return { type: COMPLETE_TODO,
index
}
}function selectFilter(filter){ return { type: SETFILTER,
filter
}
}var initState = { filter:'SHOW_ALL', todos: []
}function todoApp(state = initState,action){ switch(action.type){ case SETFILTER: return Object.assign({},state,{ filter: action.filter
}); case ADD_TODO: return Object.assign({},state,{ todos:[...state.todos,{text: action.text,complete: false}]
}); case COMPELETE_TODO: return Object.assign({},state,{ todos: return [
...state.slice(0, parseInt(action.index), Object.assign({},state[action.index],{ completed: true
}),
...state.slice(parseInt(action.index) + 1)
]
}); default: return state;
}
}
将不存在以来关系的字段拆分给不同的子 Reducer 管理。
例如 Filter 和 Todos 俩个字段不存在相互依赖。
function setFilter(state = FILTER.SHOW_ALL,action){ switch(action.type){ case SETFILTER: return action.filter; default: return state;
}
}function todos(state = [], action){ switch(action.type){ case ADD_TODO: return [...state, { text: action.type, completed: false
}]; case COMPLETE_TODO: return [
...state.slice(0,parse(action.index)), Object.assign({},state[action.index],{ completed: true
}),
...state.slice(parseInt(action.index) + 1)
]; default: return state;
}
}
将每个 Reducer 拼接起来返回一个完整的 state
// reducers -> Object// example -> reducers = { filter: setFilter, todos: todos}function combineReducers(reducers) { var reducerKeys = Object.keys(reducers) // array -> ['filter','todos']
var finalReducers = {} for (var i = 0; i 使用例子
var todoApp = combineReducers({ filter: setFilter, todos: todos
})Store
维持应用所有 State 的一个对象,也可是说一个方法的集合
var store = createStore(todoApp)
Store 的方法
getState
dispatch 唯一能改变 state 的函数
subscribe 增加监听,当 dispatch action 的时候就会触发
replaceReducer 替换当前用来计算的 reducer
var createStore = Redux.createStore;var combineReducers = Redux.combineReducers;var applyMiddleware = Redux.applyMiddleware;const ADD_TODO = 'ADD_TODO';const COMPLETE_TODO = 'COMPLETE_TODO';const SETFILTER = 'SETFILTER';const FILTER = { SHOW_ALL:'SHOW_ALL', SHOW_COMPLETE:'SHOW_COMPLETE', SHOW_ACTIVE:'SHOW_ACTIVE'}function addTodo(text){ return { type:ADD_TODO,
text
}
}function completeTodo(index){ return { type:COMPLETE_TODO,
index
}
}function selectFilter(filter){ return { type:SETFILTER,
filter
}
}var initState = { filter:'SHOW_ALL', todos:[]
}function todos(state = [], action) { switch (action.type) { case ADD_TODO: return [...state, { text: action.text, completed: false
}]; case COMPLETE_TODO: return [
...state.slice(0, parseInt(action.index)), Object.assign({}, state[action.index], { completed: true
}),
...state.slice(parseInt(action.index)+ 1)
]; default: return state;
}
}function setFilter(state = FILTER.SHOW_ALL,action){ switch(action.type){ case SETFILTER: return action.filter; default: return state;
}
}var todoApp = combineReducers({ filter:setFilter, todos:todos
});var store = createStore(todoApp);var unsubscribe = store.subscribe(()=>{ console.log(store.getState());
});console.log('添加吃饭');
store.dispatch(addTodo('吃饭'));console.log('添加睡觉');
store.dispatch(addTodo('睡觉'));console.log('完成吃饭');
store.dispatch(completeTodo(0));console.log('添加打豆豆');
store.dispatch(addTodo('打豆豆'));console.log('完成睡觉');
store.dispatch(completeTodo(0));console.log('setFilter');
store.dispatch(selectFilter(FILTER.SHOW_COMPLETE));
unsubscribe();
Action 用户发起一个动作请求的请求内容
State 保存应用现有的状态
Reducer 根据 Action 请求内容的 Type 字段去匹配要进行的动作与修改的状态
Store 存储库,把 Reducer 传入 createStore 的构造器中得到,只有通过它的 dispatch 方法传入一个 Action 请求内容,之后自动去 Reducer 中匹配 Type 字段,之后去修改相应的状态
作者:Nodelover
链接:https://www.jianshu.com/p/4417458ddab2
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/2325/viewspace-2811829/ ,如需转载,请注明出处,否则将追究法律责任。