VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > temp > JavaScript教程 >
  • react redux 二次开发流程

在一个大项目中如何引入redux及其相关技术栈(react-redux redux-thunk redux-immutable ),已经成为react前端工程师不可或缺的技能,下面通过实现一个简单的todolist效果,来介绍相关流程

 

 

1.引入redux进行应用数据管理,安装相关依赖

yarn add redux  react-redux redux-thunk redux-devtools-extension
一般目录结构

 

2.创建好store.js、reducer.js、action.js、action-types.js

1)store.js
复制代码
1 /*
2 redux最核心的管理对象store
3  */
4 import {createStore} from 'redux'
5 import reducer from './reducer'
6 
7 const  store = createStore(reducer, window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__())
8 // 向外默认暴露store
9 export default  store
复制代码

 2) reducer.js

复制代码
 1 import {CHANGEINPUT,ADDITEMS } from './action-types'
 2 
 3 const defalutState = {
 4     inputValue : 'wuxiaohui',
 5     list :[]
 6 }
 7 
 8 export default (state = defalutState,action) =>{
 9     if(action.type === CHANGEINPUT){
10         let newState = JSON.parse(JSON.stringify(state))//深拷贝
11         newState.inputValue = action.value
12         return newState
13     }
14     if(action.type === ADDITEMS){
15         let newState = JSON.parse(JSON.stringify(state))
16         newState.list.push(newState.inputValue)
17         newState.inputValue = ''
18         return newState
19     }
20 
21     return state
22 }
复制代码

3)action.js

复制代码
import {CHANGEINPUT,ADDITEMS } from './action-types'

export const inputChange = (e)=>({
    type:CHANGEINPUT,
    value:e.target.value
})

export const clickButton = ()=>({
    type:ADDITEMS
})
复制代码

4)action-types.js

/*
包含n个action type常量名称的模块
 */
export const CHANGEINPUT = 'change_input'
export const ADDITEMS = 'add_item'

3.创建todolistui组件

编写TodolistUI.js,由于没有双向绑定,通过onChange的inputChange事件拿到输入值并通过inputValue传回给输入框,clickButton则是向list中追加输入框中输入的数据,输入后清空。该逻辑在 reducer.js中体现,UI组件只负责展示。
 
复制代码
//把TodoList改为UI组件-提高性能

import React from "react";

 const TodoListUI =(props)=>{
// 接收connect连接器映射传递的属性和函数
    let {inputValue ,inputChange,clickButton,list} = props; 
    return (

        <div>
            <div>
                <input value={inputValue} onChange={inputChange} />
                <button onClick={clickButton}>提交</button>
            </div>
            <ul>
                {
                    list.map((item,index)=>{
                        return (<li key={index}>{item}</li>)
                    })
                }
            </ul>
        </div>
    );
}
export  default TodoListUI
复制代码

4.引入react-redux进行应用数据管理

1)总入口中index.js中引入react-redux和容器组件APP
react-redux的核心:Provider(用于入口) 和 connect(用于数据和函数映射)
使用provider
复制代码
/*
入口js
 */
import React from 'react';
import ReactDOM from 'react-dom';

import App from './containers/App';
import { Provider} from 'react-redux'
import store from './redux/store'

//<Provider>是一个提供器,只要使用了这个组件,组件里边的其它所有组件都可以使用store了
//声明一个App容器组件,然后这个组件用Provider进行包裹。
const  AppList = (
    <Provider store={store}>
        <App />
    </Provider>
)
ReactDOM.render(AppList, document.getElementById('root'));
复制代码
2)connect连接器(连接UI组件和redux中的action.js方法)成为容器组件
connect-连接器用来将redux管理的state数据映射成UI组件的一般属性(如输入框的值)
connect-连接器用来将redux管理的包含diaptch代码的函数映射成UI组件的函数属性的函数
1.在redux目录中的action.js定义UI组件要调用的方法,然后编写好reducer的业务逻辑
2.在containers容器APP组件中 引入UI组件TodolistUI和action进行连接
复制代码
import React from 'react'
import {connect} from 'react-redux'

import TodoListUI from '../components/TodoListUI'
import {inputChange,clickButton} from '../redux/actions'

/*
connect-连接器用来将redux管理的state数据映射成UI组件的一般属性(如输入框的值)
 指定向TodoList传入哪些一般属性(属性值的来源就是store中的state)
 */
const stateToProps = (state)=>{
    return {
        inputValue : state.inputValue,
        list:state.list
    }
}

/*
connect-连接器用来将redux管理的包含diaptch代码的函数映射成UI组件的函数属性的函数
(如输入的onChange事件)
可以写多个函数,用逗号隔开
 */
// 写法1
// const dispatchToProps = (dispatch) =>{
//     return {
//         inputChange(e){
//             //派发action到store中:定义action 然后派发
//             //派发后就在reducer里边,编写对应的业务逻辑了
//             let action = {
//                 type:'change_input',
//                 value:e.target.value
//             }
//             dispatch(action)
//         },
//         clickButton(){
//
//             let action = {type:'add_item'}
//             dispatch(action)
//         }
//     }
// }
//export default connect(stateToProps,dispatchToProps )(TodoListUI);

// 写法2
export default connect(stateToProps,{inputChange,clickButton} )(TodoListUI);
复制代码
5.引入 immutablejs
首先,我们有必要来划分一下边界,哪些数据需要使用不可变数据,哪些数据要使用原生js数据结构,哪些地方需要做互相转换
  • 在redux中,全局state必须是immutable的,这点毋庸置疑是我们使用immutable来优化redux的核心
  • 组件props是通过redux的connect从state中获得的,并且引入immutableJS的另一个目的是减少组件shouldComponentUpdate中不必要渲染,shouldComponentUpdate中比对的是props,如果props是原生JS就失去了优化的意义
  • 组件内部state如果需要提交到store的,必须是immutable,否则不强制
  • view提交到action中的数据必须是immutable
  • Action提交到reducer中的数据必须是immutable
  • reducer中最终处理state必须是以immutable的形式处理并返回
  • 与服务端ajax交互中返回的callback统一封装,第一时间转换成immutable数据

1)安装相关依赖

yarn add immutable  redux-immutable 

2)在reducer中 immutable的fromJs,把defalutState 转为immutable数据

复制代码
 1 // 引入fromJS 将state数据转变为 immutable对象
 2 const defalutState = fromJS({
 3     inputValue : 'wuxiaohui',
 4     list :[]
 5 });
 6 
 7 //immutablejs的相关接口——使用get 和set 方法来改变state
 8 export default (state = defalutState,action) =>{
 9     if(action.type === CHANGEINPUT){
10         // let newState = JSON.parse(JSON.stringify(state)) //深拷贝
11         // newState.inputValue = action.value
12         // return newState
13         return  state.set('inputValue',action.value)
14     }
15     if(action.type === ADDITEMS){
16         // let newState = JSON.parse(JSON.stringify(state))
17         // newState.list.push(newState.inputValue)
18         // newState.inputValue = ''
19         // return newState
20         
21         return state.merge({
22             'list': state.get('list').push(state.get('inputValue')),
23             'inputValue': ''
24         });
25 
26     }
27 
28     return state
29 }
复制代码

3)在容器组件中App.js中映射时使用get获取相关属性值

复制代码
 1 /*
 2 connect-连接器用来将redux管理的state数据映射成UI组件的一般属性(如输入框的值)
 3  指定向TodoList传入哪些一般属性(属性值的来源就是store中的state)
 4  */
 5 const stateToProps = (state)=>{
 6     return {
 7         // inputValue : state.inputValue,
 8         // list:state.list
 9         //因为引入了immutable,state 已变为不可变对象只能调用get或set方法
10         inputValue : state.get('inputValue'),
11         list:state.get('list')
12     }
13 }
复制代码
更多用法:
参考https://blog.csdn.net/weixin_33728268/article/details/87972634
 

4)redux-immutable在reducer的处理

combineReducers(reducers)
https://cn.redux.js.org/docs/api/combineReducers.html
随着应用变得越来越复杂,可以考虑将 reducer 函数 拆分成多个单独的函数,拆分后的每个函数负责独立管理 state 的一部分
参考文档 https://www.cnblogs.com/superlizhao/p/9474859.html

类似这样

复制代码
 1 import { combineReducers } from 'redux';
 2 import { reducer as headerReducer } from '../common/header/store';
 3 import { reducer as homeReducer } from '../pages/home/store';
 4 import { reducer as detailReducer } from '../pages/detail/store';
 5 import { reducer as loginReducer } from '../pages/login/store';
 6 
 7 const reducer = combineReducers({
 8    header: headerReducer,
 9    home: homeReducer,
10    detail: detailReducer,
11    login: loginReducer
12 });
13 
14 export default reducer;
复制代码

 

假如我们的reducer在header中,组件中获取数据时,用get方法

复制代码
const mapStateToProps = (state) => {
    //inputValue是immutable对象,不能用state.header.inputValue的形式获取,要用get()
      return  {
          inputValue :state.header.get('inputValue'),
          list:state.header.get('list')    
      }    
}
复制代码

在使用了redux-immutable

复制代码
1 //combineReducers不再用rudux里的,而是redux-immutable里的,这样combineReducers里的对象就是一个immutable对象
2 //import {combineReducers} from 'redux'
3 import {combineReducers} from 'redux-immutable'
4 import {reducer as headerReducer} from '../common/header/store'
5 const reducer=combineReducers({
6     header:headerReducer
7 });
8 export default reducer;
复制代码

获取数据的时候用get(),或者getIn()--获取结构化数据

复制代码
1 const mapStateToProps = (state) => {    
2       return  {
3           //inputValue :state.header.get('inputValue'),
4          // list:state.header.get('list') 
5              inputValue :state.getIn(['header','inputValue']),
6              list:state.getIn(['header','list'])
7       }    
8 }
复制代码
 
流程中例子详见GitHub
https://github.com/scalerone/ReduxDemo

 

如果你觉得不错的话,右下角,随手点个推荐,鼓励支持hhh^_^

相关教程