理解Redux以及如何在项目中的使用

  今天我们来聊聊Redux,这篇文章是一个进阶的文章,建议大家先对redux的基础有一定的了解,在这里给大家推荐一下阮一峰老师的文章: http://www.ruanyifeng.com/blog/2016/09/redux_tutorial_part_one_basic_usages.html       

   对于基础部分我在这里稍微讲解一下

  首先我们要知道我们为什么要使用Redux,我们在什么情况下才需要去使用Redux,在这里引用Redux的创造者的一句话:"只有遇到 React 实在解决不了的问题,你才需要 Redux 。" 

  结合项目经验说下我自己的理解:如果这批数据只是在一个组件使用并且不需要和别的组件进行数据共享,从单一来源获取数据的时候,也就是说你的UI层很简单,没有复杂的数据流动,总之就是加入数据流动单项并且很简易,没有与服务器的大量交互的情况下,我们不需要使用Redux,否则只会让我们的开发变得更加复杂。

  那么什么时候我们需要用到Redux呢:比如你的数据流动很复杂,这批数据有多个组件需要使用甚至别的页面也需要使用它,或者说就是你的某些状态需要在多个没有强关联的组件中用到,举个很常见的例子,就比如说我们做登录保存用户信息或者是做购物车的时候,我们就很有必要引入Redux来帮我们做状态管理了,总之,就是在你某些状态或者数据的很难控制很难传递的时候,你需要Redux来帮助你。

   参照这张经典图来讲解一下Redux的工作原理

                                                                           

 

  组件Component通过ActionCreators派发一个行为action(注意在这里是派发一个扁平对象),这个行为被派发到了Store,Store借助Reducer确认该State的状态并执行相应的操作,接下来Reducer把新的State返回给Store,最后Store把这个State转给了Component。

 

   假如说你已经在你使用Redux做过一些小demo了,我讲一下在项目中的一个Redux进阶用法,我就根据上面讲的Redux的工作流程,结合伪代码给大家讲解一下在项目中我们应该如何去使用它(建议把这段伪代码通读几遍,因为本人写的前后顺序排的不是很合理,但是通读下来几遍的话,相信你能理解的):

  第一步:我们要在最外面注册一个Store

import { createStore, applyMiddleware } from 'redux'    //applyMiddleware作用是提供一个中间件,关于Redux中中间件的理解大家可以去官网看一下,很有用处,链接地址:http://cn.redux.js.org/docs/advanced/Middleware.html
import thunk from 'redux-thunk' //可以让dispatch传的内容就不会局限于只能传一个扁平对象了,就可以传一个函数了,关于redux-thunk的话后期我给大家写一个它源码的解析,最近太累了,感兴趣的伙伴先自己查查
import reducers from './reducers'  

const store = createStore(reducers,applyMiddleware(thunk))   

export default store

 

  第二步:可能你会有很多个地方要用到Redux,那么你可能会有很多reducer,这个时候我们会需要redux提供的combineReducers来将我们各个地方的reducer进行合并,就会让它们互不影响

import { combineReducers } from 'redux' //为了可以引入多个reducer

//以下是伪代码,只是模拟我们有多个reducer,我们可以把它们合并起来,互不影响
import {reducer as first} from 'pages/first' import {reducer as ticket} from 'pages/ticket' export default combineReducers({ first, ticket })

  第三步:全局注入store

import { Provider } from 'react-redux'    //你可以Provider想象成一个注入器,它可以帮我们把store注入到我们的根组件上,这样的话store将无处不在
import store from './store'
ReactDOM.render(
    <Provider store={store}>
        <App />
    </Provider>,
    document.getElementById('root')
)

  接下来就是我们某个地方要如何使用Redux,假设现在的场景是这样的,我们要派发一个action,同时这个action还要去请求ajax,ajax又是异步的,这个时候我们刚才的那个thunk就有作用了,我先简单讲解一下它的作用,我们通常情况下是提交一个扁平对象,然后这个action直接送到reducer中去进行操作,但是我们有异步请求数据的时候怎么办呢,thunk给我们提供的就是我们派发行为的时候可以派发一个函数,再派发一个扁平对象,当遇到函数的时候会先执行函数里面的内容最后再去提交到reducer中,好,大概你应该懂我的意思了,开始操作:

 

       第四步:我们要触发action对吧,为了避免命名冲突,我们先来创建一个actionTypes.js文件,我们要给每个type加一个命名空间:

export const GET_COMMENT_DATA = 'ticket/get_comment_data'

export const SET_RECORD_DATA = 'ticket/set_record_data'

 

  

  第五步:我们要去派发一个action,直接把怎么拿store中的数据也写出来把

const mapDispatch = (dispatch)=>{
  return {
      loadList(){
          dispatch(loadListDataAsync(dispatch))
      }
  }
}
const mapState = (state) => {
    return {
      swiperList: state.first.list
    }
}

 

   

  第六步:我们要从react-redux中引入一个connect,它是帮助我们来可以在组件中使用dispatch和state的,写法是这样的:

export default connect(mapState,mapDispatch)(App)
记录下我之前遇到的一个小坑,之前我是只在当前组件中用到了dispatch,所以我是这样写的:
export default connect(mapDispatch)(App)      //后来发现会有一堆红色的怪物包围着我
正确的姿势其实是这样的:
export default connect(null,mapDispatch)(App)

 

   

  第七步:我们去看看我们是怎么利用thunk请求ajax数据的把:

import { GET_COMMENT_DATA } from './actionTypes'

export const LoadCommentDataAsync = (dispatch,id)=>{        
    return ()=>{              //在这个函数中我们可以进行异步请求数据
        fetch('/haha', {
            method: 'GET',
            headers: {
                'content-type': 'application/json'
            },
        })
        .then(response => response.json())
        .then(result=>{
            dispatch({            //遇到扁平对象了,可以提交到reducer了
              type: GET_COMMENT_DATA,
              comments: result
          })
        })
    }
}

 

   

  第八步:我们来到reducer中处理你的action

import { GET_COMMENT_DATA } from './actionTypes'
import { SET_RECORD_DATA } from './actionTypes'

const defaultState = {
    comments: {},
    records: []
}

export default (state=defaultState,action)=>{
    if(action.type === GET_COMMENT_DATA){
        return {
            ...state,
            comments: action.comments
        }
    }
    if(action.type === SET_RECORD_DATA){
        return {
            ...state,
            records: [...state.records,action.records]
        }
    }
    return state
}

 

  

  第九步:我们把这个reducer暴露出来,也就是我们第一步在reducers中引入的reducer

import reducer from './reducer'

export {
    reducer
}

 

 

 

    这篇写的不是很好,原谅我,最近很多事都堆在一起了,等我调整好了,这次的代码就当成全是伪代码来看,重在理解Redux的流程以及它是如何在项目中进行使用的,理解它的用法即可,相信你看懂了以后在写项目的时候会对它的理解会越来越深刻的,别看我代码是怎么写的,就看看步骤就行了,我承认这次写的很烂(:,等我调整好了给大家把注释和解释再完善完善,后期我会来修改它的

 

posted @ 2018-12-11 20:27  渴望成为大牛的男人  阅读(2859)  评论(0编辑  收藏  举报