Redux 初见

前端之家收集整理的这篇文章主要介绍了Redux 初见前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

Redux初见

本文记录的是自己对redux的学习和理解,希望可以简洁易懂,入门redux,一步步的走进redux!


Redux是什么

ReduxJavaScript应用的状态容器,提供可预测化的状态管理,让你构建一致化的应用,运行于不同的环境(客户端、服务器、原生应用),并且易于测试。不仅于此,它还提供超爽的开发体验。

核心概念

  • store】保存应用状态全局单一

  • state】所有state以key-value的形式存储在store

  • action】描述发生什么的对象,触发action是唯一改变state的方式,action本质上是一个普通js对象,必必须一个type字段,值为字符串常量

  • action creator】创建action

  • reducer】描述action如何改变state


Redux常用方法

createStore(reducer,[initialState])

创建一个Redux store来以存放应用中所有的state

combineReducers(reducers)

随着应用复杂度上升,数据源逐渐变混乱,导致组件内部数据调用十分复杂,会产生数据冗余或者混用等情况,需要对reducer函数进行拆分,拆分后的每一模块独立负责管理state的一部分。combineReducers函数的作用是,返回一个最终的rootReducer函数rootReducer做的事情是得到一个由多个不同reducer函数作为value(key可以自定义)的对象。

  1. const module1Reducer = combineReducers(
  2. module1_key1: module1_reducer1
  3. );
  4. const rootReducer = combineReducers(
  5. key1: reducer1,module1: module1Reducer
  6. );
  7. const store = createStore(rootReducer);
  8. // store中保存的state结构如下
  9. {
  10. key1: reducer1(state.key1,action),module1: {
  11. module1_key1: (state.module1.module1_key1,action)
  12. }
  13. }

总结一下,state对象的结构由传入的多个reducer的key决定,可以根据模块拆分的细粒度,考虑是否需要嵌套使用combineReducers,整个应用的数据大致分来两类:普通data和ui状态

  1. + data
  2. - 服务器响应的数据
  3. - 缓存数据
  4. - 本地尚未持久化到服务器的数据
  5. - 用户输入
  6. - ...
  7. + ui状态
  8. - 激活的路由
  9. - 被选中的Tab标签
  10. - 是否显示加载动画
  11. - 分页器状态
  12. - ...

设计state结构时,尽量把state范式化,不要存在嵌套不同类型的对象的情况。把数据放到一个对象(列表)中,每个数据用id作为主键。不同类型的对象通过id引用数据,这样数据发生改变的时候,只需要修改一处地方,减少数据冗余或者混用。

applyMiddleware(...middlewares)

首先要介绍一下什么是middlewaresmiddlewares用于包装store.dispatch,扩展其功能,在发起action之后,到达reducer之前执行一些逻辑,有点类似是aop的一种实现。
applyMiddleware大致实现:

  • 暂存redux store提供的dispatch

  • dispatch作为实参,传给middleware执行之后返回的函数A

  • 执行函数A,返回包装过的dispatch,覆盖原来的store.dispatch

  1. function applyMiddleware(store,middlewares) {
  2. middlewares = middlewares.slice()
  3. middlewares.reverse()
  4. // 暂存dispatch
  5. let dispatch = store.dispatch
  6. // 包装dispatch
  7. middlewares.forEach(middleware =>
  8. dispatch = middleware(store)(dispatch)
  9. )
  10. return {...store,{ dispatch })
  11. }

理解了applyMiddleware的逻辑,自定义一个middleware大致如下

  1. function(store){
  2. // pass store.dispatch to next
  3. return function(next){
  4. // return dispatch
  5. return function(action){
  6. // implement middleware logic
  7. }
  8. }
  9. }

bindActionCreators(actionCreators,dispatch)

  • 参数actionCreators如果为函数action creators 转成拥有同名keys的对象,但使用 dispatch 把每个action creator包围起来,返回新的对象

  • 参数actionCreators如果为对象,若actionCreators[key]为函数,用dispatch把每个 actionCreators[key]包围起来,返回新的对象

compose(...functions)

组合store enhance,applyMiddleware 和 redux-devtools就是store enhance


React-redux桥接

Redux本身只提供应用状态和数据流管理,除了和React一起用外,还支持其它界面库,且没有任何依赖。要在React的项目中使用Redux,比较好的方式是借助react-redux这个库来做连接.

provider

为整个应用提供store数据,做的事情是把store作为props传递到每一个被connet()包装的组件

connect([mapStateToProps],[mapDispatchToProps],[mergeProps],[options])

connect(...args)(component)返回一个与Redux store连接的组件类,下面简单讲解一下connect方法的参数

mapStateToProps(state,[ownProps]) [Function]
  • statestore中整个应用的state

  • ownProps高阶函数包装过的组件的props

  • 该回调函数必须返回一个纯对象,这个对象会与被包装的组件的props做merge合并

  • mapStateToProps可以做一些数据的format, filter,compose操作,保证数据在组件层面的方便使用

mapDispatchToProps(dispatch,[ownProps]) [Object or Function]
  • mapDispatchToProps参数为Object,每个定义在该对象的函数都将被当作Redux action creator,其中所定义的方法名将作为属性名,合并到被包装的组件的props中,实现的效果:执行component.prop.checkout()实际上是dispatch了一个action,这样做的好处是component与redux的解耦,component根本不知道redux的存在。

  1. // action creator返回对象
  2. mapDispatchToProps = {
  3. // action creator
  4. checkout: function actionCreator(productId){
  5. return {
  6. type: types.ADD_TO_CART,productId
  7. }
  8. }
  9. }
  10. // action creator返回函数,thunk
  11. mapDispatchToProps = {
  12. // action creator
  13. checkout: function actionCreator(productId){
  14. action creator 返回一个thunk thunk的参数为 dispatch getState
  15. return (dispatch,getState) => {
  16. if (getState().products.byId[productId].inventory > 0) {
  17. dispatch(addToCartUnsafe(productId))
  18. }
  19. }
  20. }
  21. }
  22.  
  23. // 最终被绑定的组件props
  24. component.props.checkout = function () {
  25. return dispatch(actionCreator.apply(undefined,arguments));
  26. }
  • mapDispatchToProps参数为Function

  1. mapDispatchToProps(dispatch,[ownProps]) = function(){
  2. return {
  3. checkout: () => {
  4. dispatch(actionCreator())
  5. }
  6. }
  7. }
  8. // 最终被绑定的组件.props
  9. component.props.checkout = function () {
  10. return dispatch(actionCreator.apply(undefined,arguments));
  11. }
  12.  
  13. // 使用bindActionCreators
  14. mapDispatchToProps(dispatch,[ownProps]) = function(){
  15. return bindActionCreators(actionCreator,dispatch)
  16. }
  17. // 最终被绑定的组件props
  18. component.props.actionCreator = function () {
  19. return dispatch(actionCreator.apply(undefined,arguments));
  20. }
  21.  
  22. // 使用 bindActionCreators
  23. mapDispatchToProps(dispatch,[ownProps]) = function(){
  24. return bindActionCreators({
  25. checkout’: actionCreator
  26. },dispatch)
  27. }
  28. // 最终被绑定的组件props
  29. component.props.checkout = function () {
  30. return dispatch(actionCreator.apply(undefined,arguments));
  31. }

使用redux之后应用的数据流向

  1. dispatch(actionCreator)=> Reducer => (state,action) => state

  • 用户操作或者网络请求 store.dispatch(action)

  • redux store调用传入的rootReducer

  • redux 执行全部的reducer,把每个reducer执行得到的结果输出合成一个新的对象

  • store 存储rootReducer返回的值,更新currentState

猜你在找的React相关文章