在一个大项目中如何引入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
 /*
redux最核心的管理对象store
*/
import {createStore} from 'redux'
import reducer from './reducer' const store = createStore(reducer, window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__())
// 向外默认暴露store
export default store

2) reducer.js

 import {CHANGEINPUT,ADDITEMS } from './action-types'

 const defalutState = {
inputValue : 'wuxiaohui',
list :[]
} export default (state = defalutState,action) =>{
if(action.type === CHANGEINPUT){
let newState = JSON.parse(JSON.stringify(state))//深拷贝
newState.inputValue = action.value
return newState
}
if(action.type === ADDITEMS){
let newState = JSON.parse(JSON.stringify(state))
newState.list.push(newState.inputValue)
newState.inputValue = ''
return newState
} return state
}

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数据

 // 引入fromJS 将state数据转变为 immutable对象
const defalutState = fromJS({
inputValue : 'wuxiaohui',
list :[]
}); //immutablejs的相关接口——使用get 和set 方法来改变state
export default (state = defalutState,action) =>{
if(action.type === CHANGEINPUT){
// let newState = JSON.parse(JSON.stringify(state)) //深拷贝
// newState.inputValue = action.value
// return newState
return state.set('inputValue',action.value)
}
if(action.type === ADDITEMS){
// let newState = JSON.parse(JSON.stringify(state))
// newState.list.push(newState.inputValue)
// newState.inputValue = ''
// return newState return state.merge({
'list': state.get('list').push(state.get('inputValue')),
'inputValue': ''
}); } return state
}

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

 /*
connect-连接器用来将redux管理的state数据映射成UI组件的一般属性(如输入框的值)
指定向TodoList传入哪些一般属性(属性值的来源就是store中的state)
*/
const stateToProps = (state)=>{
return {
// inputValue : state.inputValue,
// list:state.list
//因为引入了immutable,state 已变为不可变对象只能调用get或set方法
inputValue : state.get('inputValue'),
list:state.get('list')
}
}
更多用法:
 

4)redux-immutable在reducer的处理

combineReducers(reducers)
随着应用变得越来越复杂,可以考虑将 reducer 函数 拆分成多个单独的函数,拆分后的每个函数负责独立管理 state 的一部分

类似这样

 import { combineReducers } from 'redux';
import { reducer as headerReducer } from '../common/header/store';
import { reducer as homeReducer } from '../pages/home/store';
import { reducer as detailReducer } from '../pages/detail/store';
import { reducer as loginReducer } from '../pages/login/store'; const reducer = combineReducers({
header: headerReducer,
home: homeReducer,
detail: detailReducer,
login: loginReducer
}); 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

 //combineReducers不再用rudux里的,而是redux-immutable里的,这样combineReducers里的对象就是一个immutable对象
//import {combineReducers} from 'redux'
import {combineReducers} from 'redux-immutable'
import {reducer as headerReducer} from '../common/header/store'
const reducer=combineReducers({
header:headerReducer
});
export default reducer;

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

 const mapStateToProps = (state) => {
return {
//inputValue :state.header.get('inputValue'),
// list:state.header.get('list')
inputValue :state.getIn(['header','inputValue']),
list:state.getIn(['header','list'])
}
}
 
流程中例子详见GitHub

react redux 二次开发流程的更多相关文章

  1. 实例讲解基于 React+Redux 的前端开发流程

    原文地址:https://segmentfault.com/a/1190000005356568 前言:在当下的前端界,react 和 redux 发展得如火如荼,react 在 github 的 s ...

  2. OMCS开发手册(04) -- 二次开发流程

    在掌握了前面几篇关于OMCS的详细介绍后,我们就可以正式基于OMCS进行二次开发了.下面我们就从服务端和客户端的角度分别介绍开发的步骤. 一.服务端开发 抛开具体的业务逻辑而言,就OMCS的服务端的开 ...

  3. C#开发BIMFACE系列2 二次开发流程

    系列目录     [已更新最新开发文章,点击查看详细] BIMFACE 平台是一个对外开放的平台,建筑行业的相关公司.软件公司或者有 BIM 业务需求的公司都可以注册成为开发者并使用其提供的强大功能. ...

  4. 【工业串口和网络软件通讯平台(SuperIO)教程】三.二次开发流程

    1.1    二次开发流程图 1.2    引用相关组件 找到“开发包”,引用里边的相关组件.如下图: 1.3    开发设备驱动模块 1.3.1    开发发送协议驱动 继承SuperIO.Devi ...

  5. Struts2学习笔记二:开发流程

    一:创建项目,添加依赖包 二:在web.xml配置核心控制器 <filter> <filter-name>struts2</filter-name> <fil ...

  6. 如何从零搭建一个webpack+react+redux+react-redux的开发环境一入门

    阅读本文章的时候,你要有一定的基础知识储备,简单的es6知识,模块化思想知识,js基础知识,node基础知识,react等 首先执行npm init,此时我的文件叫case; 下面安装一些需要的npm ...

  7. Ecshop系统二次开发教程及流程演示

      来源:互联网 作者:佚名 时间:03-01 16:05:31 [大 中 小] Ecshop想必大家不会觉得陌生吧,大部分的B2C独立网店系统都用的是Ecshop系统,很受用户的喜爱,但是由于Ecs ...

  8. PHPCMS V9 模块开发 二次开发实例 留言本

    鄙人实现了PHPCMS V9 产品开发权威指南(2011官方最新版).doc中的留言板实例,并加上模块安装和卸载功能, 程序可以运行,但只实现基本功能,目的是想让和我一样徘徊在PHPCMS门口不知道从 ...

  9. C#开发微信公众平台开发-微信海报介绍和开发流程

    “让客户发展客户”,微信海报才是微信公众平台最高明的吸粉手段,海报上有粉丝的专属二维码,有粉丝的头像及商户宣传的广告等.新粉丝扫描这个专属二维码会关注公众号,同时分享海报的粉丝会增加积分换取礼品或者优 ...

随机推荐

  1. iOS中的几个重要方法

    iOS开发中几个重要的方法: 加载类到内存,程序刚启动的时候调用,调用在main函数之前 1.+(void)load{ } 初始化类,类第一次使用的时候调用一次 2.+(void)initialize ...

  2. POJ-2155-Matrix二位树状数组应用

    题目: 一个只有0和1构成的二维平面,给你两种指令,一种是区间的更新,即0变为1,1变为0:一种是查询一个点是1还是0: 由于是二进制,所以每次更新在相应的点上加一,最后对2取余即可. 至于二维的树状 ...

  3. Docker中使用FlameGraph分析JVM应用性能

    开源项目推荐 Pepper Metrics是我与同事开发的一个开源工具(https://github.com/zrbcool/pepper-metrics),其通过收集jedis/mybatis/ht ...

  4. mysql 查询参数尾部有空格时被忽略

    最近再使用mysql时,无意见发现,当我查询参数尾部输入若干个空格时,依然可以查出和不加空格相同的结果,像这样 select * from wa where name='be ' 等同于 select ...

  5. Java EE—最轻量级的企业框架?

    确保高效发展进程的建议 很久以前,J2EE,特别是应用程序服务器被认为过于臃肿和"重量级".对于开发人员来说,使用此技术开发应用程序会非常繁琐且令人沮丧.但是,由于 J2EE 框架 ...

  6. java读写文件IO

    package Common.readFile; import Common.tool.User; import com.fasterxml.jackson.databind.ObjectMapper ...

  7. Django与mongodb数据库的连接

    1.最开始需要下载一个第三方模块:mongoengine 2.下载完成之后,需要在settings中完成配置(在DATABASES后面,别问我为什么,问了我也不告诉你...) connect中传入的是 ...

  8. Nginx总结(六)nginx实现负载均衡

    前面讲了如何配置Nginx虚拟主机,大家可以去这里看看nginx系列文章:https://www.cnblogs.com/zhangweizhong/category/1529997.html 今天要 ...

  9. spring data jpa介绍

    首先了解JPA是什么? JPA(JavaPersistence API)是Sun官方提出的Java持久化规范.它为Java开发人员提供了一种对象/关联映射工具来管理Java应用中的关系数据.他的出现主 ...

  10. 配置hibernate访问mysql

    在之前搭建spring mvc项目这篇的基础上继续集成,引入hibernate支持 一.添加jar包引用 修改pom.xml文件,加入: <dependency> <groupId& ...