1、Redux概念简述
2、Redux的工作流程
3、使用Antd实现TodoList页面布局
4、创建Redux中的store
5、Action和Reducer的编写
6、使用Redux完成TodoList删除功能
7、ActionTypes的拆分
8、使用actionCreator统一创建action
9、Redux知识点复习补充
官方Antd文档 https://ant.design/docs/react/introduce-cn
简介: Antd 是基于 Ant Design 设计体系的 React UI 组件库,主要用于研发企业级中后台产品。
特性:
安装Antd包,打开cmd,输入以下命令行。安装完后,重启服务器。
cd <项目目录下>
$ npm install antd --save
$ npm run start
TodoList.js(重写TodoList)
import React, {
Component
} from 'react';
import 'antd/dist/antd.css';
import {
Input,
Button,
List
} from 'antd';
// 使用Antd实现TodoList布局
const data = [
'Racing car sprays burning fuel into crowd.',
'Japanese princess to wed commoner.',
'Australian walks 100km after outback crash.',
'Man charged over missing wedding girl.',
'Los Angeles battles huge wildfires.',
];
class TodoList extends Component {
render() {
return (
({item} )}
/>
)
}
}
export default TodoList;
官网redux文档 https://redux.js.org/introduction/getting-started
创建一个store进行数据管理,比作图书馆管理员
安装Redux包,打开cmd,输入以下命令行。安装完后,重启服务器。
cd <项目目录下>
$ npm install redux --save
$ npm run start
src/store/index.js(新建js文件)
import {
createStore
} from 'redux';
import reducer from './reducer'; //引入记事本
// 创建一个图书管理员store
const store = createStore(reducer);
export default store;
src/store/reducer.js(新建js文件)
// 创建记事本,记录数据信息
// state存储整个图书馆的全部信息
const defaultState = {
inputValue: '123',
list: [1, 23, 4]
};
// 返回数据
export default (state = defaultState, action) => {
return state;
}
src/TodoList.js(修改TodoList)
import React, {
Component
} from 'react';
import 'antd/dist/antd.css';
import {
Input,
Button,
List
} from 'antd';
import store from './store'; //引入管理员
// 使用Antd实现TodoList布局
class TodoList extends Component {
constructor(props) {
super(props);
// 获取store的数据
this.state = store.getState();
}
render() {
return (
({item} )}
/>
)
}
}
export default TodoList;
打开软件 -> 点击谷歌浏览器右上角三点处 -> 选择“更多工具 - 扩展程序” -> 点击“扩展程序”页面左上角”扩展程序“ -> 点击展开的侧边栏右下角的“打开Chrome网上应用店” -> 在应用店页面搜索 " redux devtools " -> 点击搜索结果 " redux devtools " 的 " 添加至Chrome " -> 添加成功后,可以在页面右上角看到redux图标 -> 重启浏览器,就可以在开发者工具看到redux一栏。
查看到redux栏目显示 Not Found,因此需要在src/store/index.js文件中createStore()添加一个参数,具体如下:
src/store/index.js(修改js文件)
...
const store = createStore(
reducer,
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
);
...
this.state = store.getState();
handleInputChange(e) {
// 创建一个请求
const action = {
type: 'change_input_value',
value: e.target.value
};
// 告知store这个请求
store.dispatch(action);
}
export default (state = defaultState, action) => {
if (action.type === 'change_input_value') {
// 对旧数据进行深拷贝
const newState = JSON.parse(JSON.stringify(state));
// 修改新数据并返回
newState.inputValue = action.value;
return newState;
}
console.log(state, action);
return state;
}
const store = createStore(
reducer,
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
);
...
this.handleStoreChange = this.handleStoreChange.bind(this);
// 声明一个函数,这个函数当store的数据一旦改变,就可自动的执行
store.subscribe(this.handleStoreChange);
...
handleStoreChange() {
//更新组件数据
this.setState(store.getState());
}
...
...
...
handleBtnClick() {
const action = {
type: 'add_todo_item',
}
store.dispatch(action);
}
...
if (action.type === 'add_todo_item') {
const newState = JSON.parse(JSON.stringify(state));
newState.list.push(newState.inputValue);
newState.inputValue = '';
console.log(newState);
return newState;
}
完整代码修改
src/TodoList.js(修改js文件)
import React, {
Component
} from 'react';
import 'antd/dist/antd.css';
import {
Input,
Button,
List
} from 'antd';
import store from './store'; //引入管理员
// 使用Antd实现TodoList布局
class TodoList extends Component {
constructor(props) {
super(props);
// 1、获取store管理的数据
this.state = store.getState();
this.handleInputChange = this.handleInputChange.bind(this);
this.handleStoreChange = this.handleStoreChange.bind(this);
this.handleBtnClick = this.handleBtnClick.bind(this);
// 6、从store获取数据,更新组件state数据
// 声明一个函数,这个函数当store的数据一旦改变,就可自动的执行
store.subscribe(this.handleStoreChange);
}
render() {
return (
({item} )}
/>
)
}
handleInputChange(e) {
// 更改store管理的数据
//2、创建一个请求
const action = {
type: 'change_input_value',
value: e.target.value
};
//3、告知store这个请求,store会自动将之前的数据previousState和当前用户想要的操作action自动转发给reducer
store.dispatch(action);
}
handleStoreChange() {
//更新组件数据
this.setState(store.getState());
}
// 7、点击提交input框内容
handleBtnClick() {
const action = {
type: 'add_todo_item',
}
store.dispatch(action);
}
}
export default TodoList;
src/store/index.js(修改js文件)
import {
createStore
} from 'redux';
import reducer from './reducer'; //引入笔记本
// 创建一个图书管理员store
// 5、store会自动地将reducer处理后返回的新数据替换掉旧数据
const store = createStore(
reducer,
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
);
export default store;
src/store/reducer.js(修改js文件)
// 创建记事本,记录数据信息
const defaultState = {
inputValue: '123',
list: [1, 23, 4]
};
// 返回数据
// state存储整个图书馆的全部信息
// reducer可以接受state,但绝不能修改state
export default (state = defaultState, action) => {
// 4、告知store如何处理change_input_value请求
if (action.type === 'change_input_value') {
// 对旧数据进行深拷贝
const newState = JSON.parse(JSON.stringify(state));
// 修改新数据并返回
newState.inputValue = action.value;
return newState;
}
// 8、告知store如何处理add_todo_item请求
if (action.type === 'add_todo_item') {
const newState = JSON.parse(JSON.stringify(state));
newState.list.push(newState.inputValue);
newState.inputValue = '';
console.log(newState);
return newState;
}
return state;
}
给列表 list 的每一项 item 绑定一个点击删除事件
src/TodoList.js(添加代码)
...
({item} )}
/>
...
//删除列表Item
handleItemDelete(index) {
const action = {
type: 'delete_todo_item',
index
};
store.dispatch(action);
}
...
src/store/reducer.js(添加代码)
...
if (action.type === 'delete_todo_item') {
const newState = JSON.parse(JSON.stringify(state));
newState.list.splice(action.index, 1);
return newState;
}
...
如果把action的type的值写错,比如TodoList.js文件中把change_input_value写成change_invt_value,到页面进行调试,发现控制台并不会报错。所以,为了更好的方便调试,将action的type名抽取出来。因此,在 src / store 文件夹下,新建一个 actionTypes.js 文件,进行记录action的Type名称。
修改如下:
src/TodoList.js(修改代码)
...
import {
CHANGE_INPUT_VALUE,
ADD_TODO_ITEM,
DELETE_TODO_ITEM
} from './store/actionTypes';
...
const action = {
type: CHANGE_INPUT_VALUE,
value: e.target.value
};
...
const action = {
type: ADD_TODO_ITEM,
};
...
const action = {
type: DELETE_TODO_ITEM,
index
};
src/store/reducer.js(修改代码)
import {
CHANGE_INPUT_VALUE,
ADD_TODO_ITEM,
DELETE_TODO_ITEM
} from './actionTypes';
...
if (action.type === CHANGE_INPUT_VALUE) {...
...
if (action.type === ADD_TODO_ITEM) {...
...
if (action.type === DELETE_TODO_ITEM) {...
...
src/store/actionTypes.js(新建js文件)
//导出常量
export const CHANGE_INPUT_VALUE = 'change_input_value';
export const ADD_TODO_ITEM = 'add_todo_item';
export const DELETE_TODO_ITEM = 'delete_todo_item';
为了便于管理action,将所有action放到actionCreator进行统一管理。作用提高代码的可维护性,方便前端做代码的自动化测试。因此,在 src / store 文件夹下,新建一个 actionCreators.js 文件,统一管理action。
代码修改如下
src/TodoList.js(修改代码)
...
// import {
// CHANGE_INPUT_VALUE,
// ADD_TODO_ITEM,
// DELETE_TODO_ITEM
// } from './store/actionTypes';
//删除以上注释代码,修改为以下代码
import {
getInputChangeAction,
getAddItemAction,
getDeleteItemAction
} from './store/actionCreators';
...
//const action = {
// type: CHANGE_INPUT_VALUE,
// value: e.target.value
//};
//删除以上注释代码,修改为以下代码
const action = getInputChangeAction(e.target.value);
...
//const action = {
// type: ADD_TODO_ITEM,
//};
//删除以上注释代码,修改为以下代码
const action = getAddItemAction();
...
//const action = {
// type: DELETE_TODO_ITEM,
// index
//};
//删除以上注释代码,修改为以下代码
const action = getDeleteItemAction(index);
src/store/actionCreators.js(新建js文件)
import {
CHANGE_INPUT_VALUE,
ADD_TODO_ITEM,
DELETE_TODO_ITEM
} from './actionTypes';
//返回一个js对象
export const getInputChangeAction = (value) => ({
type: CHANGE_INPUT_VALUE,
value
});
export const getAddItemAction = (value) => ({
type: ADD_TODO_ITEM
});
export const getDeleteItemAction = (index) => ({
type: DELETE_TODO_ITEM,
index
});