1.什么是redux
Redux不是专门给React服务的,它是一个JavaScript应用的状态容器,提供了可预测的状态数据管理方案/管理模式,可以让开发的应用行为更为稳定且可预测,同时还可以应用于不同的环境(客户端、服务器、原生应用),并且易于测试
Redux特点
状态数据可控:状态数据按照提供的通用组件和函数完成管理,数据的CRUD操作都会被监听和同步
数据集中管理:数据集中管理实现了数据和业务的分离,方便数据项的扩展和独立维护
专业调式工具: Redux Devtools可以通过可视化方式完成数据的监控和调试
丰富社区支持:Redux有自己丰富的社区技术支持,可以和大量的第三方组件一起配合使用
项目中引入redux支持
yarn add redux
Redux核心组件
state: 初始化的数据集,主要用于集中式的存储管理的状态数据
action:数据的操作方式,主要用于区分不同的数据处理方案
reducer: 数据的具体运算,主要按照数据的处理方案,执行数据运算的部分,一般情况是一个函数
2.redux工作原理
3.redux基本语法
创建状态是数据管理模块: store/index.js
import {createSore} from 'redux'
initData=[{id:1,name:'华为',price:2000},{id:2,name:'苹果',price:2999}]
function goodsReducer(state=initData,action) {
switch(action.type) {
case 'add':
break
case 'del':
break
case 'edit':
break
default:
return state
}
}
const store = createStore(goodsReducer)
export default store
数据渲染
React组件中需要引入和使用数据,数据从redux数据管理模块中进行获取和渲染
import React, { Component} from 'react'
import './layout.css'
import store from './store'
export default class Layout extends Component {
render() {
let goodsList = store.getState()
return (
<div>
{goodsList.map(item=>
<h2 key={item.id}>
<span>id:{item.id}</span>
<span>商品名:{item.name}</span>
<span>单价:{item.price}</span>
</h2>
)}
</div>
)
}
}
增加数据,编辑store/index.js
...
case 'add':
let {name,price} = action.data
let id = state.length>0 ? state[state.length-1].id+1:1
return [...state,{id,name,price}]
...
...
export default class Layout extends Component {
state={
goodsList:store.getState(),
values: {
name:'',
price:''
}
}
changeName=(event)=>{
this.state.values.name = event.target.value
this.setState({
})
}
changePrice=(event)=>{
this.state.values.price = event.target.value
this.setState({
})
}
submit=()=> {
store.dispatch({type:'add',data:this.state.values})
this.state.values.name = ''
this.state.values.price = ''
this.setState({
goodsList:store.getState()
})
}
render() {
return (
<div>
名称:<input type="text" value={this.state.values.name} onChange={(event)=>this.changeName(event)}/>
单价:<input type="text" value={this.state.values.price} onChange={(event)=>this.changePrice(event)}/>
<button onClick={this.submit}>新增</button>
{this.state.goodsList.map(item=>
<h2 key={item.id}>
<span>id:{item.id}</span>
<span>商品名:{item.name}</span>
<span>单价:{item.price}</span>
</h2>
)}
</div>
)
}
}
...
编辑数据
...
case: 'edit':
const {id,name,price} = action.data
let index = state.findIndex(item=>item.id === id)
state[index].name = name
state[index].price = price
return state
...
export default class Layout extends Component {
state={
goodsList:store.getState(),
hasId:null,
values: {
name:'',
price:''
}
}
changeName=(event)=>{
this.state.values.name = event.target.value
this.setState({
})
}
changePrice=(event)=>{
this.state.values.price = event.target.value
this.setState({
})
}
submit=()=> {
if(this.state.hasId) {
store.dispatch({type:'edit',data:{...this.state.values,id:this.state.hasId}})
}else {
store.dispatch({type:'add',data:this.state.values})
}
this.state.values.name = ''
this.state.values.price = ''
this.state.hasId = null
this.setState({
goodsList:store.getState()
})
}
edit=(item)=>{
console.log(item);
this.state.values.name = item.name
this.state.values.price = item.price
this.state.hasId = item.id
this.setState({})
}
render() {
return (
<div>
名称:<input type="text" value={this.state.values.name} onChange={(event)=>this.changeName(event)}/>
单价:<input type="text" value={this.state.values.price} onChange={(event)=>this.changePrice(event)}/>
<button onClick={this.submit}>{this.state.hasId?'编辑':'新增'}</button>
{this.state.goodsList.map(item=>
<h2 key={item.id}>
<span>id:{item.id}</span>
<span>商品名:{item.name}</span>
<span>单价:{item.price}</span>
<button onClick={()=>this.edit(item)}>编辑</button>
</h2>
)}
</div>
)
}
}
删除数据
...
case 'del':
return state.filter(goods=>goods.id!==action.data)
...
deletGoods=(id)=>{
store.dispatch({type:'del',data:{id}})
this.setState({
goodsList:store.getState()
})
}
...
{this.state.goodsList.map(item=>
<h2 key={item.id}>
<span>id:{item.id}</span>
<span>商品名:{item.name}</span>
<span>单价:{item.price}</span>
<button onClick={()=>this.edit(item)}>编辑</button>
<button onClick={()=>this.deletGoods(item.id)}>删除</button>
</h2>
)}
...
4.模块化拆分
1.拆cationType
actionType:数据操作方式
封装文件: goodsActionTypes.js
export const goodsAddType = 'goods/add'
export const goodsEditType = 'goods/edit'
export const goodsDelType = 'goods/del'
2.拆actionCreator
actionCreator:封装创建好的数据操作方案
封装文件: goodsActionCreator
import {goodsAddType,goodsEditType,goodsDelType} from './goodsActionTypes'
export const goodsAddAction = data=>({type:goodsAddType,data})
export const goodsEditAction = data=>({type:goodsEditType,data})
export const goodsDelAction = data=>({type:goodsDeleType,data})
封装goodsReducer
goodsReducer:数据运算函数,完成数据的具体业务处理
封装文件goodsReducer
import {goodsAddType,goodsEditType,goodsDelType} from './goodsActionTypes'
...
case goodsAddType
...
...
引入合并
goodsReducer函数已经被独立拆分到一个模块中,最终在 store/index.js中引入使用
...
import goodsReducer from './goodsReducer'
const store = createStore(brandReducer)
使用
import React, { Component} from 'react'
import './layout.css'
import { goodsAddAction,goodsEditAction,goodsDelAction } from './store/modules/actionCreator'
import store from './store'
export default class Layout extends Component {
state={
goodsList:store.getState(),
hasId:null,
values: {
name:'',
price:''
}
}
changeName=(event)=>{
this.state.values.name = event.target.value
this.setState({
})
}
changePrice=(event)=>{
this.state.values.price = event.target.value
this.setState({
})
}
submit=()=> {
if(this.state.hasId) {
// store.dispatch({type:'edit',data:{...this.state.values,id:this.state.hasId}})
store.dispatch(goodsEditAction({...this.state.values,id:this.state.hasId}))
}else {
// store.dispatch({type:'add',data:this.state.values})
store.dispatch(goodsDelAction(this.state.values))
}
this.state.values.name = ''
this.state.values.price = ''
this.state.hasId = null
this.setState({
goodsList:store.getState()
})
}
edit=(item)=>{
console.log(item);
this.state.values.name = item.name
this.state.values.price = item.price
this.state.hasId = item.id
this.setState({})
}
deletGoods=(id)=>{
// store.dispatch({type:'del',data:{id}})
store.dispatch(goodsDelAction({id}))
this.setState({
goodsList:store.getState()
})
}
render() {
return (
<div>
名称:<input type="text" value={this.state.values.name} onChange={(event)=>this.changeName(event)}/>
单价:<input type="text" value={this.state.values.price} onChange={(event)=>this.changePrice(event)}/>
<button onClick={this.submit}>{this.state.hasId?'编辑':'新增'}</button>
{this.state.goodsList.map(item=>
<h2 key={item.id}>
<span>id:{item.id}</span>
<span>商品名:{item.name}</span>
<span>单价:{item.price}</span>
<button onClick={()=>this.edit(item)}>编辑</button>
<button onClick={()=>this.deletGoods(item.id)}>删除</button>
</h2>
)}
</div>
)
}
}
5.多模块开发
redux提供了combineReducer用于将多个拆分管理的数据模块,最终合并多个模块
import {combineReducers} from 'redux'
const store = createStore(combineReducers({
goods:goodsReducer,
orders:ordersReducer
}))
import React, { Component} from 'react'
import './layout.css'
import { goodsAddAction,goodsEditAction,goodsDelAction } from './store/modules/actionCreator'
import store from './store'
export default class Layout extends Component {
state={
goodsList:store.getState().goods,
hasId:null,
values: {
name:'',
price:''
}
}
changeName=(event)=>{
this.state.values.name = event.target.value
this.setState({
})
}
changePrice=(event)=>{
this.state.values.price = event.target.value
this.setState({
})
}
submit=()=> {
if(this.state.hasId) {
// store.dispatch({type:'edit',data:{...this.state.values,id:this.state.hasId}})
store.dispatch(goodsEditAction({...this.state.values,id:this.state.hasId}))
}else {
// store.dispatch({type:'add',data:this.state.values})
store.dispatch(goodsAddAction(this.state.values))
}
this.state.values.name = ''
this.state.values.price = ''
this.state.hasId = null
this.setState({
goodsList:store.getState().goods
})
}
edit=(item)=>{
console.log(item);
this.state.values.name = item.name
this.state.values.price = item.price
this.state.hasId = item.id
this.setState({})
}
deletGoods=(id)=>{
// store.dispatch({type:'del',data:{id}})
store.dispatch(goodsDelAction({id}))
this.setState({
goodsList:store.getState().goods
})
}
render() {
return (
<div>
名称:<input type="text" value={this.state.values.name} onChange={(event)=>this.changeName(event)}/>
单价:<input type="text" value={this.state.values.price} onChange={(event)=>this.changePrice(event)}/>
<button onClick={this.submit}>{this.state.hasId?'编辑':'新增'}</button>
{this.state.goodsList.map(item=>
<h2 key={item.id}>
<span>id:{item.id}</span>
<span>商品名:{item.name}</span>
<span>单价:{item.price}</span>
<button onClick={()=>this.edit(item)}>编辑</button>
<button onClick={()=>this.deletGoods(item.id)}>删除</button>
</h2>
)}
</div>
)
}
}
6.解耦合
React项目中使用Redux管理状态数据,导致组件中出现了大量store.method调用方式,让两个不同技术之间的代码的耦合度太高,不利于后期项目的维护
react提供了一个模块:react-redux,转么用于解耦合react组件,redux状态管理模式
Provider: 提供者的意思,提供数据管理桥梁,让redux中的数据可以在react组件中按照固定语法直接使用,避免大量的代码耦合
固定语法:将Provider组件包裹在React应用的根组件外部
import Provider from 'react-redux'
import store './store/index'
function() {
return <Provider store={store}>
其他组件
</Provider>
}
connect() ,用于管理指定的组件,映射数据state和操作方案action
固定语法:将默认组件的导出方式,连接到数据和操作的映射关系上
import {connect} from 'react-redux'
export default connect(映射state数据,映射action函数)(goods)
代码操作
安装react-