Redux优化
redux核心
store = createStore() 创建核心 store.getState() 获取数据 store.dispatch() 调用方法 store.subscribe 监听state数据,判断是否被修改
action creator
当redux变量增多,需要区分,首先修改case条件
高效的action
action types
将type定义为变量
combineReducer
actionType.js
export const persion_add = "persion/insert" export const persion_delete = "persion/delete" export const persion_update = "persion/update"
action.js
import {persion_add,persion_delete,persion_update} from './actionType' export const persionAdd = data=>({type: persion_add,data}) export const persionDelete = index=>({type: persion_delete,index}) export const persionUpdate = (data,index)=>({type: persion_update,data,index})
reducer.js
import {persion_add,persion_delete,persion_update} from './actionType' const init_list = [ { id:3, name: "张三", age: 18 }, { id:2, name: "李四", age: 18 }, { id:1, name: "王五", age: 18 } ] function personList(state = init_list,action){ switch (action.type){ case persion_add: const obj = action.data return [obj,...state] case persion_delete: state.splice(action.index,1) return [...state] case persion_update: var index = action.index state[index] = action.data return [...state] default: return state } } export default personList
index.js
import {createStore} from 'redux' import personList from './PersionRedux/reducer' const store = createStore(personList) //创建一个store对象 export default store
layout.jsx
import React, { Component } from 'react' import store from '../redux' import {persionDelete,persionUpdate,persionAdd} from '../redux/PersionRedux/action' import { Table, Input,Form,Button } from 'antd'; import '../asserts/css/layout.css' export default class Layout extends Component { state = { dataSource: [], columns: [ { title: '编号', //表头字段 dataIndex: 'id', //调用数据对应的字段 table.id }, { title: '姓名', dataIndex: 'name', }, { title: '年龄', dataIndex: 'age', }, { title: '操作', render: (obj,a,index)=><> <Button type="primary" success='true' onClick={()=>this.edit(obj,index)}>修改</Button> <Button type="primary" danger onClick={()=>this.del(index)}>删除</Button> </> }, ], person_id: 0, person_index: 0 } UNSAFE_componentWillMount() { store.subscribe(()=>{ this.setState({dataSource:store.getState()}) // setFieldsValue this.form_ref.setFieldsValue( { name: "", age: "" } ) this.setState({person_index: 0,person_id: 0}) }) this.setState({dataSource:store.getState()}) } del(index){ store.dispatch(persionDelete(index)) } edit(obj,index){ this.setState({person_index:index}) //设置form数据 this.form_ref.setFieldsValue( { name: obj.name, age: obj.age, } ) this.setState({person_id: obj.id}) } submit(value){ var id = this.state.dataSource.length>0?this.state.dataSource[0].id+1:1 var inserData = { id, name:value.name, age: value.age } if(this.state.person_id){ inserData.id = this.state.person_id store.dispatch(persionUpdate(inserData,this.state.person_index)) }else{ store.dispatch(persionAdd(inserData)) } } render() { return ( <> <div className="yangshi"> <Form name="basic" labelCol={{ span: 8 }} wrapperCol={{ span: 16 }} initialValues={{ remember: true }} autoComplete="off" onFinish={this.submit.bind(this)} ref={dom=>this.form_ref=dom} > <Form.Item label="用户名" name="name" > <Input /> </Form.Item> <Form.Item label="年龄" name="age" > <Input /> </Form.Item> <Form.Item wrapperCol={{ offset: 8, span: 16 }}> <Button type="primary" htmlType="submit"> 保存 </Button> </Form.Item> </Form> <Table rowKey='id' dataSource={this.state.dataSource} columns={this.state.columns} /> </div> </> ) } }
使用combineReducer
react-redux
1、redux比较复杂
2、直接使用redux,会在jsx的语法当中混入相当多的redux代码
react-redux是react的一个插件
作用: 帮助我们在react项目中更优雅的使用redux
安装
npm i react-redux -S
核心对象
react-redux式辅助开发者使用redux,而不是从新定义了redux,所以还需要借助之前的redux代码,整个思路就是将redux的数据和方法写到组件本身的component的props当中。
Provider
用法:将当前组件变为标签,包裹在react跟组件外部
作用:将store的数据传递给应用
connect
是一个由返回值的高阶函数
作用:获取Provider提供的数据,并将数据绑定到react组件的props当中。
connect拥有两个参数,分别代表: 1、绑定state数据的回调函数,函数自动接受来自Provider传递的state数据 2、绑定dispatch数据的回调函数,函数自动接受来自redux的dispatch方法,可以调用Provider传递action方法 二者都需要返回一个对象,对象当中的内容会被绑定组件的props上,
完整的layout代码
import React, { Component } from 'react' import store from '../redux' import {persionDelete,persionUpdate,persionAdd} from '../redux/PersionRedux/action' import { Table, Input,Form,Button } from 'antd'; import '../asserts/css/layout.css' import {connect} from 'react-redux' class Layout extends Component { state = { dataSource: [], columns: [ { title: '编号', //表头字段 dataIndex: 'id', //调用数据对应的字段 table.id }, { title: '姓名', dataIndex: 'name', }, { title: '年龄', dataIndex: 'age', }, { title: '操作', render: (obj,a,index)=><> <Button type="primary" success='true' onClick={()=>this.edit(obj,index)}>修改</Button> <Button type="primary" danger onClick={()=>this.del(index)}>删除</Button> </> }, ], person_id: 0, person_index: 0 } UNSAFE_componentWillMount() { store.subscribe(()=>{ this.form_ref.setFieldsValue( { name: "", age: "" } ) this.setState({person_index: 0,person_id: 0}) }) } del(index){ this.props.persionDeleteAction(index) } edit(obj,index){ this.setState({person_index:index}) //设置form数据 this.form_ref.setFieldsValue( { name: obj.name, age: obj.age, } ) this.setState({person_id: obj.id}) } submit(value){ var id = this.props.persion_list.length>0?this.props.persion_list[0].id+1:1 var inserData = { id, name:value.name, age: value.age } if(this.state.person_id){ inserData.id = this.state.person_id this.props.persionUpdateAction(inserData,this.state.person_index) }else{ this.props.persionAddAction(inserData) } } render() { return ( <> <div className="yangshi"> <Form name="basic" labelCol={{ span: 8 }} wrapperCol={{ span: 16 }} initialValues={{ remember: true }} autoComplete="off" onFinish={this.submit.bind(this)} ref={dom=>this.form_ref=dom} > <Form.Item label="用户名" name="name" > <Input /> </Form.Item> <Form.Item label="年龄" name="age" > <Input /> </Form.Item> <Form.Item wrapperCol={{ offset: 8, span: 16 }}> <Button type="primary" htmlType="submit"> 保存 </Button> </Form.Item> </Form> <Table rowKey='id' dataSource={this.props.persion_list} columns={this.state.columns} /> </div> </> ) } } const mapStateToProps = (state)=>{ //connect内部调用的时候,会自动注入state对象,这个state对象数据来源Provider传参 return { persion_list: state.persion } } const mapDispathToProps = (dispatch)=>{ //在这里讲所有的action调用方法绑定props return { persionAddAction: (data)=>dispatch(persionAdd(data)), persionDeleteAction: (id)=>dispatch(persionDelete(id)), persionUpdateAction: (data,index)=>dispatch(persionUpdate(data,index)) } } export default connect(mapStateToProps,mapDispathToProps)(Layout)
汇总:
1、将昨天的redux/index.js拆分为 reducer.js 负责函数逻辑 action.js 负责脚本 actionType.js 负责定义操作类型 汇总到index.js当中 将汇总的数据通过provider传递到组件内部 在组件内部通过connect方法将数据和方法绑定到props上
bindActionCreators
selector
-
本质: 自定义方法, 对state中的数据进行处理
-
作用: 对数据进行筛选或者预处理
-
注意: selector函数必须有返回值
-
reselect
常规的selector过滤函数如果发生重复调用,会重复执行
官方并没有提供这样的功能,我们需要通过reselect来提出解决方案
安装
npm install reselect -S
核心方法
createSelector: 帮助我们创建selector函数, 并且会加入缓存机制
createSelector需要至少两个函数作为参数
-
第一个函数的作用是提供数据源, 第一个函数的返回值会自动注入最后一个处理函数中,(必须有返回值)
-
第二个函数的作用是进行最终的处理(必须有返回值)
-
import { createSelector } from "reselect" //createSelector 把第一个函数的结果作为第二个函数的参数 export const getPersionList = createSelector(function (persion_list) { return persion_list }, function (data) { return data.filter(item => { if (item.age > 25) { return true } return false }) })
1、如何不让使用者修改开发者的代码
2、函数嵌套带来的惰性原理
function B(index){ //内存1T 数组 arrry console.log("hello world") return array[index] } B(100) function A(index){ return function(){ //内存1T 数组 arrry console.log("hello world") return array[index] } } A(100)()
3、生产消费者模式
redux调试工具
安装插件
npm i redux-devtools-extension -D
修改代码
redux-thunk
redux action 默认不可以支持异步的creater
redux-thunk是redux的一个中间件
可以支持异步actionCreator(在actionCreator方法中发送异步数据请求)
安装
npm i redux-thunk -S
注册中间件
import { createStore, combineReducers, applyMiddleware } from 'redux' import personList from './PersionRedux/reducer' import {composeWithDevTools} from 'redux-devtools-extension' import thunk from 'redux-thunk' // import goodsList from './GoodsRedux/reducer' //combineReducers 可以合并多个reduser const store = createStore(combineReducers({ persion: personList, // goods:goodsList }),composeWithDevTools(applyMiddleware(thunk))) //创建一个store对象 export default store
编写异步creater