1.UI组件(渲染)和容器组件(逻辑)的拆分
将 TodoList.js 拆分成 容器组件TodoList.js 和 UI组件TodoListUI.js 。
(1)TodoList.js
import React, {Component} from 'react';
import 'antd/dist/antd.css';
import ToDoListUI from './TodoListUI';
import store from './store/index';
import {getInputChangeAction, getAddItemAction, getDeleteItemAction} from './store/actionCreators';
class TodoList extends Component {
constructor(props) {
super(props);
this.state = store.getState();
this.handleInputChange = this.handleInputChange.bind(this);
this.handleStoreChange = this.handleStoreChange.bind(this);
this.handleButtonClick = this.handleButtonClick.bind(this);
this.handleItemDelete = this.handleItemDelete.bind(this);
store.subscribe(this.handleStoreChange) //store中数据改变后执行的方法
}
render() {
return <ToDoListUI inputValue={this.state.inputValue} list={this.state.list}
handleInputChange = {this.handleInputChange}
handleButtonClick={this.handleButtonClick}
handleItemDelete={this.handleItemDelete}/>
}
handleInputChange(e) {
const action=getInputChangeAction(e.target.value);
store.dispatch(action);
}
handleStoreChange(){
this.setState(store.getState()); //执行setState后,页面才会重新渲染
}
handleButtonClick(){
const action = getAddItemAction();
store.dispatch(action)
}
handleItemDelete(index){
const action = getDeleteItemAction(index)
store.dispatch(action)
}
}
export default TodoList;
(2)TodoListUI.js
import React,{Component} from 'react';
import {Button, Input, List} from "antd";
class TodoListUI extends Component{
render(){
return (
<div style={{marginTop: 10, marginLeft: 10}}>
<div>
<Input value={this.props.inputValue}
placeholder="todo info"
style={{width: 300, marginRight: '10px'}}
onChange={this.props.handleInputChange}/>
<Button type="primary" onClick={this.props.handleButtonClick}>提交</Button>
<List style={{marginTop: 10, width: 300}}
bordered
dataSource={this.props.list}
renderItem={(item,index) => (
<List.Item onClick={(index)=>{this.props.handleItemDelete(index)}}>{item}</List.Item>
)}
/>
</div>
</div>
)
}
}
export default TodoListUI;
2.无状态组件(当一个组件内只有render()函数的时候,我们可以使用无状态组件替换之前的普通组件)
普通组件中包含render等生命周期函数,消耗性能;而无状态组件就是一个函数,因此性能高。
将上面的 UI组件TodoListUI.js 替换 为下面的无状态组件TodoListUI.js:
import React from 'react';
import {Button, Input, List} from "antd";
const TodoListUI = (props)=>{
return (
<div style={{marginTop: 10, marginLeft: 10}}>
<div>
<Input value={props.inputValue}
placeholder="todo info"
style={{width: 300, marginRight: '10px'}}
onChange={props.handleInputChange}/>
<Button type="primary" onClick={props.handleButtonClick}>提交</Button>
<List style={{marginTop: 10, width: 300}}
bordered
dataSource={props.list}
renderItem={(item,index) => (
<List.Item onClick={(index)=>{props.handleItemDelete(index)}}>{item}</List.Item>
)}
/>
</div>
</div>
)
};
export default TodoListUI;
3.Redux中发送异步请求获取数据(与react中的ajax请求类似,只不过是通过Redux Flow流程进行)
4.使用Redux-thunk中间件进行ajax请求发送
(1)安装redux-thunk中间件:npm install redux-thunk
(2)创建store时,使用thunk中间件(同时使用devtools开发者工具)
文档:https://github.com/zalmoxisus/redux-devtools-extension中的1.2 Advanced store setup。
redux-thunk中间件:使得可以在action中写异步代码。
之前创建的action只能是js对象,使用redux-thunk后可以是函数。但store接受的action只能是对象,当store检测到action是一个函数时,会自动的执行该函数。该函数首先进行ajax获取数据,然后改变store中的数据(遵循redux流程,创建action,dispatch(action)。)
开发复杂项目时,最好将异步操作、复杂的业务逻辑,不要放在生命周期函数、组件内,将其拆分到其他地方。此处可以借助redux-thunk将其放到actionCreator中进行管理。
1.TodoList.js
import {getInputChangeAction, getAddItemAction, getDeleteItemAction, getTodoList} from './store/actionCreators';
componentDidMount() {
const action = getTodoList();
store.dispatch(action); //action动作是一个函数,当处理这个action时,就会执行该函数
}
2.actionCreators.js
import axios from "axios";
//没有使用thunk中间件之前,action只能返回对象如上所示,使用thunk后可以返回函数
export const getTodoList = () => {
return (dispatch)=>{
axios.get('/list.json').then((res)=>{
const data=res.data;
const action = initAjaxListAction(data);
dispatch(action);
})
}
};