深入浅出理解Redux

Redux是什么

Redux 是 JavaScript 状态容器,提供可预测化的状态管理。

它认为:Web应用是一个状态机,视图与状态一一对应。从架构层面来说,通常希望UI跟数据、逻辑分离,直观体现就是:UI = render(state)

为什么要用Redux

现在的Web应用涉及大量数据交互、异步操作等,无疑都在增加前端的复杂性,需要维护的state也越来越多。而Redux就是试图让每个state变化都是可预测,将应用中所有的action与state统一管理。

Redux的三原则

  • 单一数据源 整个应用state应该只存储在唯一一个的Store中。
  • 保持状态只是只读 不能直接修改state,唯一能改变Store的state方法就是通过触发一个action对象完成。
  • 数据改变通过纯函数完成 action改变state需要通过reducers。

Redux工作流程

在讲Redux的工作流程之前,需了解几个Redux相关的核心概念:

  • Action:Action可以看成是应用发出的通知,表示State应该要发生变化了,Action的触发可能是用户对View层的操作也可能是服务器的响应。
  • Action Creator:如果有很多种Action,而每种Action都手写的话显得麻烦,所以用定义的Action Creator函数来生成Action。
  • Dispatch:Action发出的唯一方法。
  • Store:整个应用唯一保存数据的地方。
  • State:对Store中保存数据生成某个时点数据快照,该数据集合叫做State。
  • Reducer:Action只是描述了State应要发生变化,而Reducer做的是如何改变State。

具体工作流程: 用户通过View(或服务器响应)触发Action,Dispatch方法将Action Creator函数生成的Action派发到Store,Store自动调用Reducer,并向它传入当前State和Action,Reducer返回新的State,State一旦有变化,Store就会通过监听函数来更新View。 借用一张图来描述这一过程:

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

几个Redux核心概念实例

以从服务器响应文章内容为例 Action

const LOAD_ARTICLES_DETAIL = 'LOAD_ARTICLES_DETAIL'
const LOAD_ARTICLES_DETAIL_SUCCESS = 'LOAD_ARTICLES_DETAIL_SUCCESS'
const LOAD_ARTICLES_DETAIL_ERROR = 'LOAD_ARTICLES_DETAIL_ERROR'
复制代码

Action Creator

export const loadArticlesDetail = () => ({
  type: LOAD_ARTICLES_DETAIL
})
export const loadArticlesDetailSuccess = result => ({
  type: LOAD_ARTICLES_DETAIL_SUCCESS,
  result
})
export const loadArticlesDetailFailure = error => ({
  type: LOAD_ARTICLES_DETAIL_ERROR,
  error
})
复制代码

Store

const store = createStore(reducers)
复制代码

Reducer (previousState, action) => (newState)

export default (state = initalState, action) => {
switch (action.type) {
case LOAD_ARTICLES_DETAIL: {
  return {
    ...state,
    loading: true,
    error: false
  }
}
case LOAD_ARTICLES_DETAIL_SUCCESS: {
  return {
    ...state,
    loading: false,
    error: false,
    articlesDetail: action.result
  }
}
case LOAD_ARTICLES_DETAIL_ERROR: {
  return {
    ...state,
    loading: false,
    error: true
  }
}
default:
  return state
}
}

复制代码

深入到Redux的源码

Redux主要源码整体结构:

  • 入口文件 index.js
export {
  createStore,
  combineReducers,
  bindActionCreators,
  applyMiddleware,
  compose
}
复制代码

这是入口文件导出的方法,也是Redux支持的方法,这些方法的实现在主工作流程文件和辅助函数文件,接下来看主工作流程。

  • 主工作流程文件 createStore.js createStore方法主要是生成Store,看看它做了哪些事儿:
    • getState方法返回了当前State
    • subscribe方法传入函数到监听队列和返回取消订阅函数
    • dispatch方法调用Reducer,按顺序执行listener,返回Action 辅助源码文件:
  • applyMiddleware.js:用于增强Store
export default function applyMiddleware(...middlewares) {
  return (createStore) => (reducer, preloadedState, enhancer) => {
    const store = createStore(reducer, preloadedState, enhancer)
    let dispatch = store.dispatch
    let chain = []

    const middlewareAPI = {
      getState: store.getState,
      dispatch: (...args) => dispatch(...args)
    }
    chain = middlewares.map(middleware => middleware(middlewareAPI))
    dispatch = compose(...chain)(store.dispatch)

    return {
      ...store,
      dispatch
    }
  }
}
复制代码

从源码上看,最后是返回了一个Store和一个被更新过的dispatch方法,实现了对Store的增强。

  • bindActionCreators.js:
export default function bindActionCreators(actionCreators, dispatch) {
  if (typeof actionCreators === 'function') {
    return bindActionCreator(actionCreators, dispatch)
  }
}
复制代码

使用dispatch把action creator都包装起来,这样可以直接调用它们。

  • combineReducers.js:当应用比较大的时而拆分Reducer,但是传入Store的Reducer必须是一个函数,所以这个方法的主要功能是用来合并多个Reducer。
  • compose.js
    export default function compose(...funcs) {
      if (funcs.length === 0) {
        return arg => arg
      }
    
      if (funcs.length === 1) {
        return funcs[0]
      }
    
      return funcs.reduce((a, b) => (...args) => a(b(...args)))
    }
    复制代码
    compose这个方法,传入的一系列函数,执行的最终结果是把各个函数串联起来。

总结:

  • Redux 是 JavaScript 状态容器,提供可预测化的状态管理。
  • 严格的单向数据流是 Redux 架构的设计核心。
  • UI = render(state)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值