亲宝软件园·资讯

展开

React Redux

小绵杨Yancy 人气:0

一、Redux

和vuex一样,redux的出现是为了管理web应用的公共状态。

这些 state 可能包括服务器响应、缓存数据、本地生成尚未持久化到服务器的数据,也包括 UI 状态,如激活的路由,被选中的标签,是否显示加载动效或者分页器等等。

二、Redux的组成

2.1 store

store 就是保存数据的地方,整个应用只能有一个 store,可以理解为一个存储数据的仓库。

redux 提供 createStore 这个函数,用来创建一个store 以存放整个应用的 state:

import { createStore } from 'redux';
const store = createStore(reducer, [preloadedState], [enhancer]);

可以看到,createStore 接受 reducer初始 state(可选)和增强器(可选)作为参数,返回一个新的 store 对象.

2.2 state

state就是store 对象包含所有数据,如果要获取当前时刻的 state,可以通过 store.getState() 方法拿到:

import { createStore } from 'redux';
const store = createStore(reducer, [preloadedState], [enhancer]);
const state = store.getState();

2.3 action

const action = {
  type: 'ADD_TODO',
  payload: 'Learn Redux' // 可选属性 可自定义名称
};

所以action可以理解为视图层向store发送的一个命令(通知),它包含了需要执行的事件(type属性)以及传递的数据(自定义属性)。

2.4 reducer

const reducer = function (state = initState, action) {
  // ...
  return new_state;
};

创建store时,第一个参数就是reducer:

const store = createStore(reducer);

那么如何向store发送action呢?

store.dispatch({
  type: 'ADD_TODO',
  payload: 'Learn Redux'
});

store对象拥有dispath方法发送action,参数就是需要传递的action对象,然后reducer接收到action并处理,返回新的state,视图自动更新。

三、三大原则

Redux 可以用这三个基本原则来描述:

3.1 单一数据源

整个应用的 state 被储存在一棵 object tree 中,并且这个 object tree 只存在于唯一一个 store 中。

console.log(store.getState())
/* 输出
{
  visibilityFilter: 'SHOW_ALL',
  todos: [
    {
      text: 'Consider using Redux',
      completed: true,
    },
    {
      text: 'Keep all state in a single tree',
      completed: false
    }
  ]
}
*/

3.2 State只读

唯一改变 state 的方法就是触发 action,action 是一个用于描述已发生事件的普通对象。

这样确保了视图和网络请求都不能直接修改 state,相反它们只能表达想要修改的意图。因为所有的修改都被集中化处理,且严格按照一个接一个的顺序执行,因此不用担心竞态条件(race condition)的出现。 Action 就是普通对象而已,因此它们可以被日志打印、序列化、储存、后期调试或测试时回放出来。

store.dispatch({
  type: 'COMPLETE_TODO',
  index: 1
})
store.dispatch({
  type: 'SET_VISIBILITY_FILTER',
  filter: 'SHOW_COMPLETED'
})

所以返回新的state时不能直接修改参数state,而是在不修改参数state的基础上返回新的state。

例如完成一个新增todo的功能:

case 'ADD_TODO':
      return state.push({
          text: action.text,
          completed: false
        })

这样是不会生效的,应为这样直接修改了state的值,正确的做法应该是:

 case 'ADD_TODO':
	    return [
	      ...state,
	      {
	        text: action.text,
	        completed: false
	      }
	    ]

这里使用了扩展运算符(…)将数组展开然后和新增的todo合并,对象同样可以使用扩展运算符达到新增属性的目的。

3.3 使用纯函数修改State

为了描述 action 如何改变 state tree ,你需要编写 reducers

Reducer 只是一些纯函数,它接收先前的 stateaction,并返回新的 state。刚开始你可以只有一个 reducer,随着应用变大,你可以把它拆成多个小的 reducers,分别独立地操作 state tree 的不同部分,因为 reducer 只是函数,你可以控制它们被调用的顺序,传入附加数据,甚至编写可复用的 reducer 来处理一些通用任务,如分页器。

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 'COMPLETE_TODO':
      return state.map((todo, index) => {
        if (index === action.index) {
          return Object.assign({}, todo, {
            completed: true
          })
        }
        return todo
      })
    default:
      return state
  }
}
import { combineReducers, createStore } from 'redux'
//合并reducer
let reducer = combineReducers({ visibilityFilter, todos })
//利用reducer创建store
let store = createStore(reducer)

四、基于Redux的TodoList

效果:

todes的reducer:

const initTodos = [
  {
    id: 1,
    text: "睡觉

加载全部内容

相关教程
猜你喜欢
用户评论