redux核心、react-redux、bindActionCreators、selector、reselect、redux-thunk

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

猜你喜欢

转载自blog.csdn.net/qq_48469083/article/details/121359776