React ( Action Creator/ ActionTypes/reducer/redux devTools调试工具/react-redux/redux高阶/项目目录设计)

Action Creator:action创建函数是将action作为一个函数进行封装,为了在store和view中进行方便调用

  actionCreator = {
    // changeName是一个函数,是actionCreator的一个方法.
    // 调用这个方法,就会返回一个对象,这个对象就是action
    changeName: (name) => ({ type: CHANGENAME, name: name }),
    changeAge: (age) => ({ type: CHANGEAGE, age: age }),
  }

ActionTypes:用来管理整个项目所有的action的type

  export const CHANGEAGE = 'changeAge';
  export const CHANGENAME = 'changeName';
  import {CHANGEAGE, CHANGENAME} from './type'
  // 修改数据的纯函数:reducer
  const reducer = (state=initState, action)=>{
  // action就是一个js的obj,一定会有一个属性叫type:{type: xxx, name: 'Jack'}
  switch (action.type) {
    case CHANGENAME:
      // 返回一个对象,作为新的state
      return {
        ...state,
        name: action.name
      }
    case CHANGEAGE:
      return {
        ...state,
        age: action.age
      }
  
    default:
      return state
  }
}
  import {CHANGEAGE, CHANGENAME} from '../store/type'
  actionCreator = {
    // changeName是一个函数,是actionCreator的一个方法.
    // 调用这个方法,就会返回一个对象,这个对象就是action
    changeName: (name) => ({ type: CHANGENAME, name: name }),
    changeAge: (age) => ({ type: CHANGEAGE, age: age }),
  }

将type.js中的变量导入到各个组件以及store中,保证整个项目的每个action的type属性都使用这里的变量,提高项目的可维护性。

reducer的拆分与合并

通过modules拆分不同模块的代码,再通过combineReducers方法将他们联合,最终创建store

  // 导入不同模块中的内容
  import orderReducer from './modules/order'
  import userReducer from './modules/user'
​
  // 通过combineReducers方法,合并两个模块中的reducer
  let rootReducer = combineReducers({
    order: orderReducer,
    user: userReducer,
  })
  const store = createStore(rootReducer);
​
  export default store

其中,info模块代码如下,user模块类似,详见代码部分。

  // 初始化数据
  const initState = {
    // 订单列表
    info: {}
  }
​
  // 统一处理action的type
  const type = {
    CHANGEINFO: 'changeInfo'
  }
​
  // 统一处理action,这里会生成所有的action
  const actions = {
    changeList: (info) => ({type: type.CHANGEINFO, info})
  }
​
  const reducer = (state = initState, action)=> {
    switch (action.type) {
      case type.CHANGEINFO:
        return {
          ...state,
          info: action.info
        }
      default:
        return state
    }
  }
​
  export default reducer;

redux devTools调试工具:类似vue-devtools,可以在浏览器中看到当前数据状态等信息

  1. 打开chrome->扩展程序->选择下载好的devTool工具(地址:Releases · zalmoxisus/redux-devtools-extension · GitHub,选择firefox即可)

  2. 安装依赖包 cnpm i redux-devtools-extension --save-dev

  3. 在代码中使用

  import {composeWithDevTools} from 'redux-devtools-extension'
  const store = createStore(rootReducer,composeWithDevTools(applyMiddleware()))
  export default store

react-redux

react-redux是redux的官方react绑定库,即为react准备的比较特殊的redux版本。它能够使你的React组件从redux store中读取数据,并且向store分发actions以更新数据 作用:为了方便组件关联状态

  1. 安装 cnpm i react-redux --save

  2. 在src/index.js中使用

  // 全局引入store,方便全局使用
  import store from './store'
  // 引入Provider组件,将store放在全局使用
  import { Provider } from 'react-redux'
  ReactDOM.render(
    // 使用Provider组件,包着其他内容,store就可以全局使用了.
    // 通过父传子的形式,将store的数据传给App
    <Provider store={store}>
      {/* 使用BrowserRouter组件包裹着App组件 */}
      <BrowserRouter>
        <App />
      </BrowserRouter>
    </Provider>,
    document.getElementById('root')
  );
  1. 在组件中使用 react-redux 提供connect方法,用于从 UI 组件生成容器组件。react-redux将组件分成两类:容器型组件(有数据和逻辑)、UI组件(没有数据和逻辑,只是呈现内容)

    let ReactRedux = connect(mapStateToProps, mapDispatchToProps)(ReactReduxUI)
    // ReactReduxUI是ui组件,通过connect()使他变成了容器型组件(ReactRedux),暴露容器性组件出去
    export default ReactRedux
  1. 容器型组件VS展示型组件

容器型组件 展示型组件
关注点 逻辑[取数据,更新数据] UI的展现
对redux是否感知
读数据 从redux的store 中获取 从props中获取
写数据 发送redux actions 调用props的回调
如何创建 通过react-redux connect创建 手写
  1. mapStateToProps类似vuex中的mapState和mapGetters,将数据映射到组件中,用来获取数据

  2. mapDispatchToProps类似vuex中的mapAction和mapMutation,将修改数据的方法映射到组件中,用来触发数据的修改

redux高阶

  1. bindActionCreators:将单个或多个ActionCreator转化为dispatch(action)的函数集合形式,统一返回

  // 导入bindActionCreators,将各个action一起导入
  import {bindActionCreators} from 'redux'
  const mapDispatchToProps = (dispatch) => ({
    changeInfo: (info) => dispatch(userAction.changeInfo(info)),
    // changeList: (list) => dispatch(orderAction.changeList(list)),
    // addList: (list) => dispatch(orderAction.addList(list)),
    // delList: (list) => dispatch(orderAction.delList(list)),
    // 将修改数据的方法一次性全部导入(订单模块的方法全部导入)
    orderAction: bindActionCreators(orderAction, dispatch)
  })

Redux中间件

Redux middleware 提供了一个分类处理 action 的机会。在 middleware 中,我们可以检阅每一个流过的 action,并挑选出特定类型的 action 进行相应操作,以此来改变 action。

  1. 自己封装中间件

  // store/index.js
  // 1.封装中间件
  const logger = store=>next=>action=>{
    console.log('调用dispatch的action',action);
    let result = next(action)
    console.log('调用dispatch后的state为',store.getState());
    return result
  }
  const store = createStore(rootReducer,composeWithDevTools(applyMiddleware(logger)))
  1. redux-logger中间件,使用action的中间件,一般放在参数的最后一位

  • 下载 cnpm i redux-logger --save

  • 引入 // 引入redux-logger import {logger} from 'redux-logger'

  • 使用

  store/index.js
  const store = createStore(rootReducer,composeWithDevTools(applyMiddleware(logger)))
  export default store

项目目录设计

  1. 按照类型划分

  actions       #action creator
    action1.js
      action2.js
  reducers  #reducer函数
    reducer1.js
      reducer2.js
  containers    #容器型组件
    container1.jsx 
      container2.jsx 
  components    #展示型组件
    components1.js
      components2.js

总结:如果需要修改一个功能,则需要修改好几个文件.

  1. 按照功能设计

  feature1        #功能1
      components  #展示型组件
          compoents1.jsx
      index.j    #容器型组件
      reducer.js #reducer函数
      actrions.js #action creator
  feature2        #功能2
      components  #展示型组件
          compoents2.jsx
      index.j    #容器型组件
      reducer.js #reducer函数
     actrions.js #action creator

总结:如果按照功能设计来来分.数据会存在重复使用,会造成代码冗余的效果

  1. ducks设计模式 ducks模式将reducer,action Type和actions绑定到同一个目录中.导致减少样板.

  src
      -components     #公共组件
      pages
          Order
              index.js    #容器型组件
              components
                  Order.jsx   #展示型组件
          User
              index.js    #容器型组件
              components
                  User.jsx    #展示型组件
      store
          index.js    #store状态对象
          modules
              Order.js    #子模块:state, action Types action Creator, reducer, action selector
              User.js     #子模块:state, action Types action Creator, reducer, action selector
             
上一篇:简述react、redux、react-redux、redux-saga、dva之间的关系


下一篇:Github Action 怎么突然间就跑不通了?