redux是一个状态管理器,核心就是状态,所以需要转变思考问题的方式,只需要考虑页面有哪些可以抽象的对象或者是要展示的对象,他们可能存在的state是什么?会有哪些动作可以改变他们自身的状态。
就拿官方的 todos 这个 待办项来说:
todos待办项github地址
其实就是需要添加 待办事项 ,操作待办事项,条件筛选展示。
-
首先是确定的是这个待办事项目的单一数据源,也就是整体的state,其实
整个应用的
state
被储存在一棵 object tree 中,并且这个 object tree 只存在于唯一一个
store
中。从显示来看,这个完整的state对象只需要两个属性:todos就是所以添加的待办事项,visibilityfilter就是展示的筛选条件,只需要这些状态就可以描述所有这个项目的任何操作和可能性。
console.log(store.getState()) /* 输出 { visibilityFilter: 'SHOW_ALL', todos: [ { text: 'Consider using Redux', completed: true, }, { text: 'Keep all state in a single tree', completed: false } ] }
-
确定了state的话就可以考虑使用什么 action 来触使state发生变化,首先是添加 待办事项,考虑到添加这一动作会改变 state中的 todos属性,也就是待办事项列表,所以添加待办事项就是一个 action,action就是有action创建函数生成的 普通对象。需要包括基本的属性 type,type就是一段字符串,最好是语义化常量,还有其他属性就是会改变的 state属性,这里添加待办事项 其实就是要往state中的todos加入对象,需要传递的state就是待办事项内容,也就是 text,所以添加待办事项action 就是:
function addTodo(text) { return { type: ADD_TODO, text } }
完整的待办事项项目的action如下:
/* * action 类型 */ export const ADD_TODO = 'ADD_TODO'; export const TOGGLE_TODO = 'TOGGLE_TODO' export const SET_VISIBILITY_FILTER = 'SET_VISIBILITY_FILTER' /* * 其它的常量 */ export const VisibilityFilters = { SHOW_ALL: 'SHOW_ALL', SHOW_COMPLETED: 'SHOW_COMPLETED', SHOW_ACTIVE: 'SHOW_ACTIVE' } /* * action 创建函数 */ export function addTodo(text) { return { type: ADD_TODO, text } } export function toggleTodo(index) { return { type: TOGGLE_TODO, index } } export function setVisibilityFilter(filter) { return { type: SET_VISIBILITY_FILTER, filter } }
-
而后就是reduce,reduce干的事就是根据上面的action来操作state,这就是redux所谓的可预知的状态管理,为了以后维护和管理方便。所以不相关的action处理最好仿作多个不同的reduce来处理,通过
combineReducers
处理,需要知道reduce是根据当前state和action来更新state的,所以reduce的分割最好是根据不想关联的state进行区分,最后设计为:
import { combineReducers } from 'redux' import { ADD_TODO, TOGGLE_TODO, SET_VISIBILITY_FILTER, VisibilityFilters } from './actions' const { SHOW_ALL } = VisibilityFilters function visibilityFilter(state = SHOW_ALL, action) { switch (action.type) { case SET_VISIBILITY_FILTER: return action.filter default: return state } } function todos(state = [], action) { switch (action.type) { case ADD_TODO: return [ ...state, { text: action.text, completed: false } ] case TOGGLE_TODO: return state.map((todo, index) => { if (index === action.index) { return Object.assign({}, todo, { completed: !todo.completed }) } return todo }) default: return state } } const todoApp = combineReducers({ visibilityFilter, todos }) export default todoApp
-
Store
就是把它们联系到一起的对象。Store 有以下职责:- 维持应用的 state;
-
提供
getState
(
)
方法获取 state; -
提供
dispatch
(
action
)
方法更新 state; -
通过
subscribe
(
listener
)
注册监听器; -
通过
subscribe
(
listener
)
返回的函数注销监听器。
import { createStore } from 'redux' import todoApp from './reducers' let store = createStore(todoApp)
这样就创建了store,可这么反过来理解,store的结构主要是reduce来确定的,主要是看怎么分解reduce,reduce就根据stire来分解的。这样可以把store传入组建中,不过需要通过connect获取。
<Provider store={store}> <App /> </Provider>,
-
store、action、reduce的关系可以这么想,store会结合所有的reduce来形成整个完整的state tree。store通过dispatch来进行state更新,这个过程就是state把当前的完整state tree根据所有的reduce来拆分下去,作为每个reduce的第一个参数state,并把action传入作为第二个参数来进行更新state tree;还有需要注意的就是store怎么把当前完整的state tree传入到组建中呢?就是上面说的 provider + connect来实现的。
版权声明:本文为caoweiju原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。