index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import TodoList from "./components/TodoList";
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<TodoList />
</React.StrictMode>
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
TodoList.js
import React,{Component}from 'react';
import TodoListUi from'./TodoListUi' //组件UI部分
import store from '../redux/store'//组件中获得store中的数据
//import {ADD_ITEM ,DELETE_ITEM} from'../store/actionTypes’//定义type类型的js 为了更方便检査错误!
import { addItem,deleteItem,getTodoList } from '../redux/actionCreators' //封装的action
class TodoList extends Component {
constructor(props) {
super(props)
//console.log(store.getState())//getState方法取出仓库的值
this.state = store.getState()//将组件state数据赋值给仓库数据
this.changeInputValue = this.changeInputValue.bind(this)//给方法做this绑定
this.storeChange = this.storeChange.bind(this)
this.clickBtn = this.clickBtn.bind(this)
this.deleteItem = this.deleteItem.bind(this)
store.subscribe(this.storeChange)//订阅模式,改变数据时同步让仓库中的数据,
}
render() {
return (
<TodoListUi
value={this.state.value}
changeInputValue={this.changeInputValue}
clickBtn={this.clickBtn}
list={this.state.list}
deleteItem={this.deleteItem}
></TodoListUi>
);
}
componentDidMount() {
const action = getTodoList()//使用中间件获取数据
store.dispatch(action)//传给仓库
}
//用户输入的值传给仓库要通过dispatch()方法传递给store
//Action就是一个对象,这个对象一般有两个属性,第一个是对Action的描述,第二个是要改变的值。
//之前注销的方法,在reducer里深拷贝完state里面的数据,无法同步将用户输入赋值给state
changeInputValue(e) {
this.setState({
value: e.target.value //将用户输入的value绑定给仓库中的vqlue,监听用户输入
})
}
//state和组件的值同步互相改变
storeChange() {
this.setState(store.getState())
}
//增加 因为list数据存在中央仓库里 所以要做的是 将组件数据传给仓库 改变仓库数据后 再返回给组件展示
clickBtn() {
const action = addItem(this.state.value);
store.dispatch(action)
}
//删除
deleteItem(index) {
const action = deleteItem(index)
store.dispatch(action)
}
}
export default TodoList;
TodoListUi.js
import React from "react";
//import 'antd/dist/antd.css'; // 通常建议使用整个antd的样式文件,而不仅仅是reset.css
import { Input, Button, List } from "antd";
const TodoListUi = (props) => {
return (
<div style={{ margin: "100px" }}>
<div>
<Input
style={{ width: "250px", marginRight: "20px" }}
onChange={props.changeInputValue}
value={props.value}
/>
<Button type='primary' onClick={props.clickBtn}>增加</Button>
</div>
<div style={{ margin: "10px", width: "300px" }}>
<List
bordered // 修正拼写错误
dataSource={props.list} // 修正属性名
renderItem={(item, index) => (
<List.Item onClick={() => props.deleteItem(index)}>{item}</List.Item>
)}
/>
</div>
</div>
);
}
export default TodoListUi;
actionCreators.js
import {ADD_ITEM,DELETE_ITEM ,GET_LIST} from'./actionTypes'//定Xtype类型的js
import axios from 'axios'
//增加数据
export const addItem =(value)=>({
type: ADD_ITEM,
value
})
//删除数据
export const deleteItem=(index)=>({
type: DELETE_ITEM,
index
})
//获取数据
export const getListAction=(data)=>({
type: GET_LIST,
data
})
export const getTodoList=()=>{
return(dispatch)=>{
axios.get('getList/mock.json')
//此处请求的是模拟数据,也可以访问用真实后端获接口API,注意data1是需要是一个数组的json
.then((res)=> {
const data1 = res.data;
const action = getListAction(data1)
dispatch(action) //将action这个值传给仓库
})
.catch((error)=> {
console.log(error)
})
}
}
actionTypes.js
//集中管理页面reducer的type类型
export const ADD_ITEM = "addItem" //定义常量一般用大写
export const DELETE_ITEM = "deleteItem"
export const GET_LIST = "getListAction"
reducer.js
import {ADD_ITEM ,DELETE_ITEM ,GET_LIST} from './actionTypes'//定xtype类型的js文件
const defaultState ={
value:'测试',
list:[]
}
export default (state=defaultState,action)=>{
if(action.type === ADD_ITEM) { //根据type值,编写业务逻辑
let newState = JSON.parse(JSON.stringify(state))
newState.list.push(action.value) //用户输入的新内容push新的内容到列表中去
console.log(action)
newState.value = ''//增加后清空
return newState
}
if(action.type === DELETE_ITEM )
{
let newState = JSON.parse(JSON.stringify(state))
newState.list.splice(action.index, 1)//删除数组中对应的值
return newState
}
if(action.type === GET_LIST ){
let newState =JSON.parse(JSON.stringify(state))
newState.list =action.data
return newState
}
return state
}
store.js
import {createStore,applyMiddleware,compose} from 'redux'//引入redux
import thunk from'redux-thunk'//引入redux中间件插件
import reducer from'./reducer'
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__?
window._REDUX_DEVTOOLS_EXTENSION_COMPOSE__({}):compose
const enhancer =composeEnhancers(applyMiddleware(thunk))
const store=createStore(reducer,enhancer)// 创建数据存储仓库
export default store //将仓库导出