redux文档解读

单一数据源

整个应用的state被储存在一棵object tree中,并且这个object tree只存在于唯一个store中。来自于服务器端的state也可以序列化之后直接注入客户端中

    console.log(store.getState())
    //输出
    {
        visibility: 'SHOW_ALL',
        todos: [
            {
               text: 'using redux',
               completed: true
            },
            {
               text: 'keep all state in a single tree',
               completed: false
            }
        ]
    }

State是只读的

唯一改变state的方法就是触发action,action是一个用于描述已发生事件的普通对象。
这样确保了视图和网络请求都不能直接修改state,它们只能触发一个action,至于是否修改state,由action的集中处理决定。action严格按照先后顺序执行,不用担心race condition竞态条件。action是普通对象,可以被日志打印,序列化等等,相当于可以自定义的event

   store.dispatch({
       //action的type属性为大写,是action的区分标识
       type: 'COMPLETE_TODO',
       //可以附带其他key:value键值对
       index: 1
   })
   store.dispatch({
      //下文reducer中用到
      type: 'SET_VISIBILITY_FILTER',
      filter: 'SHOW_COMPLETED'
    })

实际开发中,当我使用localstorage对state进行持久化存储时,不能通过直接清除localstorage来删除某一个state,而应该触发一个DELETE的action来清除state

使用纯函数-reducer

reducer是一些纯函数,接收先前的state和action,并返回新的state,刚开始可以只有一个reducer,当应用变大的时候,可以根据业务逻辑拆分成多个reducer,分别操作state tree的不同部分,

    function visibilityFilter(state='SHOW_ALL', action){
        switch(action.type){
            //上文的action
            case 'SET_VISIBILITY_FILTER':
                //返回状态
                return action.filter
            default:
                return state
        }
    }

Action

Action是把数组从应用传到store层的载体,它是store数据的唯一来源,添加新todo任务的action是这样的:

    const ADD_TODO = 'ADD_TODO'
    {
        type: ADD_TODO,
        text: ''
    }

创建一个action需要action创建函数

    function addTodo(text){
        return {
            type: ADD_TODO,
            text: ''
        }
    }

触发一次action则是发起一次dispatch过程

    diapatch(addTodo(text))

也可以创建一个变量动态绑定

   const boundAddTodo = (text) => dispatch(addTodo(text))
   //相当于boundAddTodo = function(text){ return dispatch(addTodo(text)) }

所以可以直接调用

   boundAddTodo(text);

Store

action 来描述“发生了什么”, reducers 根据 action 更新 state,而store就是把它们联系到一起的对象,Store有以下职责
1. 维持应用的state
2. 提供getState()方法获取当前state
3. 提供dispatch(action)方法更新state
4. 通过subscribe(listener)注册监听器
5. 通过subscribe(listener)返回的函数注销监听器
redux应用只有单一的store, 当需要拆分数据处理逻辑时,应该使用 reducer 组合而不是创建多个 store。

数据流

redux的数据流遵循以下4个步骤
1. 调用store.dispatch(action),可以在任何地方调用 store.dispatch(action),包括组件中、XHR 回调中、甚至定时器中。
2. Store 会把两个参数传入 reducer: 当前的 state 树和 action
3. Redux 原生提供combineReducers()辅助函数,来把根 reducer 拆分成多个函数,用于分别处理 state 树的一个分支。

    function todos(state = [], action) {
       // 省略处理逻辑...
       return nextState;
     }

     function visibleTodoFilter(state = 'SHOW_ALL', action) {
       // 省略处理逻辑...
       return nextState;
     }
    //拆分后将多个函数合并
     let todoApp = combineReducers({
       todos,
       visibleTodoFilter
     })
  1. Redux store 保存了根 reducer 返回的完整 state 树。

再谈Reducer

开发复杂的应用时,不可避免会有一些数据相互引用。尽可能地把 state 范式化,不存在嵌套。把所有数据放到一个对象里,每个数据以 ID 为主键,不同实体或列表间通过 ID 相互引用数据。把应用的 state 想像成数据库。例如,实际开发中,在 state 里同时存放 todosById: { id -> todo } 和 todos: array 是比较好的方式
另外,在return state的时候

   return Object.assign({}, state, {
        visibilityFilter: action.filter
   })

不要修改state, 不能使用 Object.assign(state, { visibilityFilter: action.filter }),因为它会改变第一个参数的值。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值