← 返回首页
React基础教程(二十二)
发表时间:2022-07-06 11:11:12
react-redux实现TodoList

react-redux实现TodoList。

项目结构图如下:

package.json

"devDependencies": {
    "@babel/core": "^7.18.5",
    "@babel/plugin-transform-runtime": "^7.18.5",
    "@babel/preset-env": "^7.18.2",
    "@babel/preset-react": "^7.17.12",
    "babel-loader": "^8.2.5",
    "css-loader": "^6.7.1",
    "css-minimizer-webpack-plugin": "^4.0.0",
    "html-webpack-plugin": "^5.5.0",
    "mini-css-extract-plugin": "^2.6.1",
    "sass": "^1.52.3",
    "sass-loader": "^13.0.0",
    "style-loader": "^3.3.1",
    "terser-webpack-plugin": "^5.3.3",
    "webpack": "^5.73.0",
    "webpack-cli": "^4.10.0",
    "webpack-dev-server": "^4.9.2",
    "webpack-merge": "^5.8.0"
  },
  "dependencies": {
    "@babel/runtime": "^7.18.3",
    "react": "^16.8.0",
    "react-dom": "^16.8.0",
    "react-router-dom": "^5.2.1",
    "redux": "^4.2.0",
    "redux-thunk": "^2.4.0",
    "axios": "^0.27.2",
    "react-redux": "^5.1.2"
  }

Input.js

import React, { Component } from 'react'

export default class Input extends Component {
    render() {
        let {width,height,size,defaultValue} = this.props
        return (
            <input style={{
                        width: width,
                        height: height,
                        fontSize: size
                    }} 
                    value={defaultValue}
                    onChange={(event)=>{defaultValue= event.target.value;}}
                    onInput={this.handleInput.bind(this)}
                    onKeyPress={this.handleEnter.bind(this)}
            />
        )
    }

    //输入事件
    handleInput(e){
        this.props.onInput(e.target.value)
    }
    //回车事件
    handleEnter(e){
        if(e.key === 'Enter'){
            this.props.onEnter(e.target.value)
        }
    }
}

List.js

import React, { Component } from 'react'

export default class List extends Component {
    render() {
        return (
            <ul>
                { this.showList() }
            </ul>
        )
    }
    //用于渲染li
    showList(){
        if(!this.props.data || this.props.data.length === 0) return <li>暂无数据</li>
        return this.props.data.map((item,index)=>{
            return (
                <li key={index}>
                    {item}
                    <button onClick={this.handleUpdateClick.bind(this,index,item)}>修改</button>
                    <button onClick={this.handleDelClick.bind(this,index,item)}>删除</button>
                </li>
            )
        })
    }
    //删除按钮点击事件
    handleDelClick(index,item){
        this.props.onDelete(index,item)
    }
    //修改按钮点击事件
    handleUpdateClick(index,item){
        this.props.onUpdate(index,item)
    }
}

store/typeName.js

const CHANGE_VALUE = 'CHANGE_VALUE'
const ADD_LIST = 'ADD_LIST'
const UPDATE_LIST = 'UPDATE_LIST'
const DELETE_LIST = 'DELETE_LIST'

const typeNames = {
    CHANGE_VALUE,
    ADD_LIST,
    UPDATE_LIST,
    DELETE_LIST
}
export default typeNames

store/reduxmap.js

import tn from './typeName'

//提供state数据的映射
function mapStateToProps(state){
    return {
        inputValue: state.inputValue,
        list: state.list
    }
}

//提供操作dispatch的函数映射
function mapDispatchToProps(dispatch) {
    return {
        changeValue(val){ //输入框的改变事件
            let action = {
                type: tn.CHANGE_VALUE,
                inputValue: val
            }
            dispatch(action)
        },
        addList(val){ //添加元素事件,即Input组件的回车事件
            let action = {
                type: tn.ADD_LIST,
                inputValue: val
            }
            dispatch(action)
        },
        updateListItem(index){ //修改元素
            let value = prompt('请输入:')
            if(!value) return
            let action = {
                type: tn.UPDATE_LIST,
                value,
                index
            }
            dispatch(action)
        },
        deleteListItem(index){ //删除元素
            let action = {
                type: tn.DELETE_LIST,
                index
            }
            dispatch(action)
        }
    }
}
const mapFunction = {
    mapStateToProps,
    mapDispatchToProps
}
export default mapFunction

store/reducer.js

import tn from './typeName'
let defaultState = {
    inputValue: '',
    list: []
}

let reducer = (state = defaultState, action) => {

    //更新输入的值
    if(action.type === tn.CHANGE_VALUE){
        let tempState = JSON.parse(JSON.stringify(state))
        tempState.inputValue = action.inputValue
        return tempState
    }

    //添加数据
    if(action.type === tn.ADD_LIST){
        let tempState = JSON.parse(JSON.stringify(state))
        tempState.list.push(action.inputValue)
        tempState.inputValue = ''
        return tempState
    }

    //更新数据
    if(action.type === tn.UPDATE_LIST){
        let tempState = JSON.parse(JSON.stringify(state))
        tempState.list.splice(action.index,1,action.value)
        return tempState
    }

    //删除数据
    if(action.type === tn.DELETE_LIST){
        let tempState = JSON.parse(JSON.stringify(state))
        tempState.list.splice(action.index,1)
        return tempState
    }

    return state
}
export default reducer

store/index.js

import {legacy_createStore as createStore} from 'redux'
import reducer from './reducer'

let store = createStore(reducer)

export default store

App.js

import React, { Component } from 'react'
import { connect } from 'react-redux'
import map from './store/reduxmap'
import Input from './Input'
import List from './List'

class App extends Component {
    render() {
        let { inputValue, list, changeValue, addList, updateListItem, deleteListItem } = this.props

        return (
            <div>
                <Input defaultValue={inputValue}
                    onInput={changeValue}
                    onEnter={addList}
                />
                <List data={list}
                    onUpdate={updateListItem}
                    onDelete={deleteListItem}
                />
            </div>
        )
    }
}
export default connect(map.mapStateToProps, map.mapDispatchToProps)(App)

index.js

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App'
import {Provider} from 'react-redux'
import store from './store'

ReactDOM.render(
    <Provider store={store}>
        <App></App>
    </Provider>
    ,document.getElementById('root'));

运行效果: