React-redux

Redux解耦合

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-redux

yarn add react-redux

编辑App.jsx

import {Provider} for 'react-redux'
...
function App() {
	return (
		<Provider><Goods/></Provider>
	)
}
...
import React, { Component} from 'react'
import './layout.css'
import { goodsAddAction,goodsEditAction,goodsDelAction } from './store/modules/actionCreator'
import {connect} from 'react-redux'
import store from './store'
class Layout extends Component {
    state={
        goodsList:store.getState().goods,
        hasId:null,
        values: {
            name:'',
            price:''
        }
    }
   componentDidMount() {
       store.subscribe(()=>{
           this.setState({})
       })
   }
    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}))
            this.props.goodsEditAction({...this.state.values,id:this.state.hasId})
        }else {
            // store.dispatch({type:'add',data:this.state.values})
            // store.dispatch(goodsAddAction(this.state.values))
            this.props.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.props.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>
        )
    }
}
const mapStateToProps = state=>{
    return {
        goods: state.goods
    }
}
const mapActionsToProps = dispatch=> ({
    goodsAddAction:goods=>dispatch(goodsAddAction(goods)),
    goodsDelAction:goods=>dispatch(goodsDelAction(goods)),
    goodsEditAction:goods=>dispatch(goodsEditAction(goods))
})
export default  connect(mapStateToProps,mapActionsToProps)(Layout)

1.数据条件过滤

redux是react组件的状态管理模式,负责管理组件中的所有数据,在数据处理过程中也包含根据条件进行数据过滤的行为,如过滤商品中价格超过200商品
1.selectore
自定义数据过滤函数,创建 store/modules/goods/goodsSelector.js

export function goodsByPriceSelector(goodsList,price) {
	return goodsList.filter(goods=>goods.price>price)
}

编辑主页,添加条件过滤函数,完成数据过滤

import {goodsSelector} from './goodsSelector'
...
state=this.props.goods
state=this.props.goodsCondition
...
const mapStateToProps = state => {
	return {
		goods:state.goods,
		goods:goodsByPriceSelector(state.goods,200)
	}
}

存在的问题,自定义数据条件过滤函数,存在同样的数据在多次访问时重复执行的问题,可以进行性能优化操作

2.reselect
描述:服务于redux数据条件过滤的一个第三方模块
作用:主要用于定义数据条件过滤操作

yarn add reselect

编辑文件 store/modules/goods/goodsSelector.js

import {createSelector} from 'reselect'
export const goodsByPriceSelector= createSelector(function(goodsList){
//第一个参数:是一个函数,用于将传如的数进行预处理
//让数据符合后续的运算条件,如果可以进行格式转化,结构重新设计
	return goodsList
},function(dataSource){
//第二个参数,是一个函数,主要用于数据的条件过滤
//参数数据:是第一个函数的返回值
return dataSouce.filter(goods=>goods.price>5000)
})

通过运行结果发现,如果条件过滤数据没有发生变化,reselect中就会直接使用上次缓存的数据结果,而不会再次执行内部的算法进行数据过滤,优化了系统执行性能

数据中如果需要进行数据过滤操作时,就需要考虑这里的数据过滤情况
如果每次数据的过滤条件都基本不一致,可以使用自定义过滤函数,避免了其他模块的引入,降低了编码复杂度的同时优化了模块/数据的加载
如果数据的多次过滤的条件经常出现一致的情况,可以使用第三方模块reselect完成数据过滤,优化数据过滤算法重复执行的问题

2.Action语法优化

1.Action语法优化
通过redux管理组件状态模式之后,所有的数据都被管理起来了,通过ActionCreator完成React组件和状态数据之间的操作关系,封装的actionCreators.js中定义了各种可能的数据操作方式

import {
    goodsAddType,goodsEditType,goodsDelType
} from './actionTypes'
export const goodsAddAction = data=>({type:goodsAddType,data})
export const goodsEditAction = data=>({type:goodsEditType,data})
export const goodsDelAction = data=>({type:goodsDelType,data})

需要在React页面组件中引入使用

import {
	goodsAddAction,
	goodsEditActions,
	goodsDelActions
} from './goodsActionsCreator'

存在的语法问题:每增加一种数据的操作方式,就需要做如下两个操作步骤

actionCreators.js中,定义一个新的数据操作方式
React组件Goods.jsx中,通过import再引入新定义的操作方式
React认为上述的操作方式,降低了开发效率,提供了goodsActionCreators用于优化引入操作方式的代码
编辑: Goods.jsx

import * as actions from '../store/moules/goodsActionCreator'
import {bindActionCreators} from 'redux'
const mapActionToprops = dispatch=> bindActionCreators(action,dispatch)

2.Action扩展案例
新增数据初始化Action,编辑 src/store/modules/goodsTypes.js

export const goodsInitType = 'goods/init' //新增一个初始化操作类型

编辑src/store/modules/goodsActionCreators.js

import {
	...
	brandInitType
} from './goodsTypes'
export const goodsInitAction = data=>({type:goodsInitType,data})

编辑src/store/modules/goodsReducer.js

import {
	...
	goodsInitType
} from './goodsActionTypes'
function goodsReducer(state=initData,action) {
	switch(action.type) {
		case goodsInitType:
			return action.data
	}
}

编辑 Goods.jsx,初始化redux管理的数据

UNSAFE_componentWillMount() {
	let axiosData=[
		{id:1,name:'小米',price: 2999},
		{id:2,name:'OPPO',price: 1999}
	]
}

3.redux-devtools

1.redux-devtools
作用:用于配合react应用,完成redux管理的状态的监控
类型:浏览器插件
2.redux-devtools-extension

yarn add redux-devtools-extension

编辑数管理模块:store/index.js 添加调试模块的支持

import {composeWithDevTools} from 'redux-devtools-extension'
const store = createStore

4.异步数据加载

1、React组件中初始化数据
初始化数据由React组件获取
编辑Goods.jsx

UNSAFE_componentWillMount() {
	axios.get('url').then(response=>{
		if(response.data.code === 200) {
			this.props.brandInitAction(response.data.list)
		}
	})
}

存在的问题:数据管理的职责划分不清楚,导致后期数据部分的维护难以升级

2.Redux管理数据
项目应用中,每个组件的职责划分清除,便于后期项目的维护

React组件:页面视图的渲染,数据更新的请求的发出
Redux组件:数据管理,如初始化、读取、新增、编辑、删除等
编辑goodsActionCreators.js

import axios from 'axios'
import {
	goodsAddType,
	goodsEditType,
	goodsDelType,
	goodsInitType
} from './goodsActionTypes'
export const goodsAddAction = data=> ({type:goodsAddType,data})
export const goodsEditAction = data=> ({type:goodsEditType,data})
export const goodsDelAction = data=> ({type:goodsDelType,data})
return dispatch=> {
	axios.get("url").then(response=>{
		if(response.data.code === 200) {
			dispatch(goodsInitAction(response.data.list))
		}
	})
}

编辑组件Goods.jsx

UNSAFE_componentWillMount(){
	this.props.goodsAxiosDataAction() //组件加载时,通知redux需要更新数据
}

注意:如果在actionCreators中添加了自定义函数,发现出现了报错
项目中安装插件 redux-thunk

yarn add redux-thunk

编辑数据管理模块 src/store/index.js,添加中间件支持

import {applyMiddleware} from 'redux'
import thunk from 'redux-thunk'
const store = createStore(combineReducers({
	goods:goodsReducer,
	order: orderReducer
}),composeWithDevTools(applyMiddleware(thunk)))
上一篇:Vue-vuex仓库的使用


下一篇:用iPad开发iPhone App,苹果发布Swift Playgrounds 4