资讯专栏INFORMATION COLUMN

Redux 初见

trigkit4 / 2743人阅读

摘要:函数的作用是,返回一个最终的函数,做的事情是得到一个由多个不同函数作为可以自定义的对象。把数据放到一个对象列表中,每个数据用作为主键。不同类型的对象通过引用数据,这样数据发生改变的时候,只需要修改一处地方,减少数据冗余或者混用。

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可以自定义)的对象。

    const module1Reducer = combineReducers(
        module1_key1: module1_reducer1
    );
    const rootReducer = combineReducers(
        key1: reducer1,
        module1: module1Reducer
    );
    
    const store = createStore(rootReducer);
    
    // store中保存的state结构如下
    {
        key1: reducer1(state.key1, action),
        module1: {
            module1_key1: (state.module1.module1_key1, action)
        }
    }
   

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

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

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

applyMiddleware(...middlewares)

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

暂存redux store提供的dispatch

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

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

    function applyMiddleware(store, middlewares) {
        middlewares = middlewares.slice()
        middlewares.reverse()
        // 暂存dispatch
        let dispatch = store.dispatch
        // 包装dispatch
        middlewares.forEach(middleware =>
            dispatch = middleware(store)(dispatch)
        )
        return {...store, { dispatch })
    }

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

    function(store){
        // pass store.dispatch to next 
        return function(next){
            // return dispatch
            return function(action){
                // implement middleware logic
            }
        }
    }
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的存在。

    // action creator返回对象 
    mapDispatchToProps = {
        // action creator
        checkout: function actionCreator(productId){
            return {
                    type: types.ADD_TO_CART,
                    productId
              }    
        }
    }
    // action creator返回函数,thunk
    mapDispatchToProps = {
        // action creator
        checkout: function actionCreator(productId){
            action creator 返回一个thunk, thunk的参数为 dispatch 和 getState
            return (dispatch, getState) => {
                  
                if (getState().products.byId[productId].inventory > 0) {
  
                         dispatch(addToCartUnsafe(productId))
                  
                }
            
            }
        }
    }

    // 最终被绑定的组件props
    component.props.checkout = function () {
        return dispatch(actionCreator.apply(undefined, arguments));
      }

mapDispatchToProps参数为Function

    mapDispatchToProps(dispatch, [ownProps]) = function(){
        return {
            checkout: () => {
                  
                dispatch(actionCreator())
        
            }
        }
    }        
    // 最终被绑定的组件.props
    component.props.checkout = function () {
            return dispatch(actionCreator.apply(undefined, arguments));
      }

    // 使用bindActionCreators
    mapDispatchToProps(dispatch, [ownProps]) = function(){
        return bindActionCreators(actionCreator, dispatch)
    }
    // 最终被绑定的组件props
    component.props.actionCreator = function () {
        return dispatch(actionCreator.apply(undefined, arguments));
      }

    // 使用 bindActionCreators
    mapDispatchToProps(dispatch, [ownProps]) = function(){
        return bindActionCreators({
            ‘checkout’: actionCreator
        }, dispatch)
    }
    // 最终被绑定的组件props
    component.props.checkout = function () {
                return dispatch(actionCreator.apply(undefined, arguments));
      }
使用redux之后应用的数据流向
dispatch(actionCreator) => Reducer => (state, action) => state

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

redux store调用传入的rootReducer

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

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

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/80116.html

相关文章

  • koa2系列教程:koa2应用初见

    摘要:系列教程,持续更新系列教程应用初见系列教程处理静态文件系列教程使用模板引擎系列教程路由控制中间件系列教程综合搭建登录注册页面系列教程实现登录注册功能这篇教程主要介绍构建服务器,简单引用本教程的版本要格外注意版本号案例简单利用搭建服务器文件夹 koa2系列教程,持续更新 koa2系列教程:koa2应用初见 koa2系列教程:koa2处理静态文件 koa2系列教程:koa2使用模板引擎 ...

    import. 评论0 收藏0
  • 初见函数式编程

    摘要:在学习的过程中时常会听到一个名次函数式编程,那么究竟什么是函数式编程,函数式编程又有什么优点,这就在这篇博客进行一个简单的总结吧主要内容函数式编程的概念函数式编程的优点与示例什么是函数式编程首先,我们放下编程的概念,我们来看函数。 在学习 JS 的过程中时常会听到一个名次——函数式编程,那么究竟什么是函数式编程,函数式编程又有什么优点,这就在这篇博客进行一个简单的总结吧~ 主要内容: 函...

    jerryloveemily 评论0 收藏0
  • 初见 g6 图表库

    摘要:准备好数据节点节点节点坐标节点坐标边节点,从哪里出发节点,到哪里结束初始化对象容器渲染位置,表示渲染到图表的中间位置画布高渲染数据这是渲染出来的效果。链接线会以元素为基准。绘制元素时,需要在初始化对象的时候,指定。 hello world // 1. 准备好数据 // node(节点) let nodes = [ { id: 1, // 节点 id ...

    LittleLiByte 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<