Redux 架构详解

Redux 是一种前端“架构模式”,是 Flux 架构的一种变种,用来提供可预测的状态管理。虽然常常和 React 一块儿被说起,可是 Redux 却不只仅只能用于 React,还能够将其运用到其余前端库中,Vue Angular甚至是 jQueryRedux 只是一种架构模式而已,并无和其余库绑定在一块儿。而 React-redux 就是把 ReduxReact.js 结合起来的一个库。就像 Vuex 同样,是一个与 Vue.js 结合的 Flux 变种。前端

为何要用 Redux

也许有人会问:为何咱们会须要 redux 呢? 嗯... 确实,咱们必需要先了解咱们为何须要 redux? redux 的出现是为了解决什么问题?react

那么,咱们来考虑这么一种场景,在你构建的一棵组件树中,有A、B那么两个组件,它们须要共享同一个状态,你会怎么办呢?redux

咱们能够经过状态提高的思路,将该状态提高到附近的公共父组件上面,而后经过 props 把状态传递给子组件,这样就能够在AB组件之间共享数据了。确实能够,可是若是AB的父组件在组件树向上好几个组件的位置呢?就须要将状态经过 props 一级一级往下传递,那么状态的传递路径就会很是长,并且中间组件根本就不须要访问这个状态。并且,若是后续有一个C 组件也要访问该状态而且ABC的公共父组件还要往上呢?你就不得不修改以前代码了。很显然,这不是一种很好的解决方案,它会让咱们的代码维护起来很是痛苦。微信

难道就没有其余方法能够解决这个问题吗?其实也有的,那就是 reactcontext,一个组件只要往本身的 context 里面放了某些状态,那么这个组件的全部子组件均可以直接访问这个状态而不须要经过中间组件的传递,看起来问题解决了嘛。架构

咱们虽然解决了状态传递的问题却引入了新的问题,咱们引入的 context 打破了组件和组件之间经过 props 传递数据的规范,极大地加强了组件之间的耦合性。并且 context 就像全局变量同样,里面的数据能够被子组件随意更改,可能会致使程序不可预测的运行。函数

这时候咱们就该考虑使用 Redux 了,Redux 能够帮你建立应用的共享状态,而且不能随意的更改这些状态。spa

Redux 的基本概念

咱们已经了解了为何要使用 Redux,那么咱们先了解下 Redux 的三个基本概念。
设计

Store

咱们能够经过 createStore 来建立 storecode

import { createStore } from 'redux';
const store = createStore(reducers);

Redux 中,应用程序只能拥有一个 store,用来保存整个应用程序的 state,至关于一个应用程序的共享状态。对象

咱们能够经过 store.getState() 来获取应用程序的当前状态。可是咱们却不能随意的修改状态,咱们只能经过 store.dispatch(action) 来修改状态。

修改完状态以后,咱们但愿能够作些 view 层的改变,这时能够经过 store.subscribe(() => {}) 来注册视图变化的回调函数。

Actions

Actions 是一个 JavaScript 普通对象,用来描述应用程序中发生的一些事情,也是把数据从应用传递给 store 的惟一途径。

咱们约定,action 内必须使用一个字符串类型的 type 字段来表示将要执行的动做,type 通常会被定义成字符串常量。

const ADD_TODO = 'ADD_TODO'

{
  type: ADD_TODO,
  data: 'some data'
}

咱们除了直接以 JavaScript 普通对象的形式来定义 action 以外,也能够经过函数形式来定义 action,这个函数被称做 Action 建立函数( actionCreator )。

const ADD_TODO = 'ADD_TODO';

function addTodo(data) {
  return {
    type: ADD_TODO,
    data
  }
}

这里 action 建立函数 addTodo 很简单,只是返回一个 action。 咱们能够经过 store.dispatch 来通知须要修改状态

store.dispatch(addTodo('some data'));

Reducers

咱们已经知道能够经过 action 来修改状态,可是 action 传递过来的只是简单的对象,并无具体处理状态的逻辑,这就是 reducers 要作的事情了。

Reducer 必须是一个纯函数(一个函数的返回结果只依赖于它的参数,而且在执行过程里面没有反作用,这个函数就叫作纯函数)。由于纯函数很是“靠谱”,执行一个纯函数不会产生不可预料的行为,也不会对外部产生影响。

function todoApp(state = { title: 'todoApp', todos: [] }, action) {
  switch (action.type) {
    case ADD_TODO:
      return Object.assign({}, state, {
        todos: [
          ...state.todos,
          {
            data: action.data,
            completed: false
          }
        ]
      })
    default:
      return state
  }
}

todoApp 接收旧的 stateaction,并返回新的 state。注意这里咱们是将 state 拷贝一份,再添加咱们改动的值去覆盖原来的数据,从新组合成新的 state 返回,而不是直接修改 state

这是由于若是你直接去改变 state 里对象的属性,那么就须要去比较新旧两个 state 的区别,而比较两个 Javascript 对象全部的属性是否相同就须要对它们进行深比较。可是在真实的应用中 js 的对象都很大,进行深比较的代价十分昂贵。而若是你返回的是一个全新的对象,就只须要比较新旧两个对象的存储地址是否相同就能够了。Redux 就是这么作的,若是你在 reducer 内部直接修改旧的 state 对象的属性值,那么新的 state 和旧的 state 将都指向同一个存储地址,Redux 会认为没有任何改变。

咱们能够有多个 reducer,每一个 reducer 只负责管理全局 state 中它负责的那部分,每一个 reducerstate 参数能够都不一样,分别对应它管理的那部分 state 数据。而后经过 combineReducers 组成根 reducer 用来建立一个 store

import { combineReducers } from 'redux';

const todosReducer = (state = [], action) => {
  // do something
}

const titleReducer = (state = '', action) => {
  // do something
}

const reducer = combineReducers({
  todos: todosReducer,
  title: titleReducer
});

// 等价于
function reducer(state = {}, action) {
  return {
    todos: todosReducer(state.todos, action),
    title: titleReducer(state.title, action)
  }
}

combineReducers 这个函数会调用你的定义的 reducer,每一个 reducer 根据它们的 key(todos, title) 来筛选出 state 中的一部分数据处理并返回一份副本,根 reducer 会把这些副本组合起来造成一个新的大对象。最后根 reducer 将这个大对象传回给 storestore 再将它设为最终的状态。

Redux 工做流程

redux 一些基本概念咱们都清楚了,咱们来总结一下,Redux 为咱们所作的事情:

  1. 一个存放应用程序共享 state 的地方
  2. 一个去分发 actions 经过纯函数修改应用程序共享 state 的机制
  3. 一个能够订阅 state 更新的机制

严格的单向数据流是 Redux 架构的设计核心。

咱们只要清楚了 redux 中的数据流动的过程就明白 redux 整个工做流程了,咱们从产生一个 action 的切入点来分析数据是怎样流动的。

  1. 经过用户在视图层的交互产生了一个 action,这个 action 多是经过 actionCreator 返回的。
  2. store 接受这这个 action 以后,将当前的 stateaction 一块儿传递给根 reducer
  3. reducerstate 分配给子 reducer 进行处理,子 reducer 返回修改后的副本给根 reducer,根 reducer 整合子 reducer 返回的副本生成一个新的 state 副本返回给 store
  4. store 根据新的 state 触发视图层的渲染。
  5. 用户看到交互后视图的变化,又高兴地发起了一个 action ...

更多精彩内容,欢迎关注微信公众号~

相关文章
相关标签/搜索