1、UI组件和容器组件
-
UI组件负责页面UI渲染,只关注页面渲染
-
容器组件负责页面逻辑处理,只关注业务逻辑
-
通过把一个组件的页面渲染代码和逻辑处理拆分成父子组件,各司其职,更清晰,更明了
-
需要注意的是:
子组件调用父组件方法函数时,还会遇到this指向问题。
因为需要获取index的值,UI组件里用箭头函数来代替父组件bind(this)。code demo 详细可参考本人上一篇博客:React-Redux入门文章
-
TodoList.js
import React,{Component} from 'react';
import store from './store';
import {getAddItemAction,deleteItemAction,getChangeItemAction } from './store/actionCreator';
import TodoListUI from './TodoListUI';
class TodoList extends Component {
constructor(props) {
super(props);
this.state = store.getState();
store.subscribe(this.handleStoreChange);
}
render(){
return <TodoListUI
handleInputChange={this.handleInputChange}
inputValue={this.state.inputValue}
handleAddItem={this.handleAddItem}
list={this.state.list}
deleteItemClick={this.handleDeleteItem}
/>
}
handleInputChange = (e) => {
const action = getChangeItemAction(e.target.value);
store.dispatch(action);
}
handleAddItem = () => {
const action = getAddItemAction();
store.dispatch(action);
}
handleDeleteItem = (index) => {
const action = deleteItemAction(index);
store.dispatch(action);
}
handleStoreChange = () => {
this.setState(store.getState());
}
}
export default TodoList;
- TodoListUI .js
import React,{Component} from 'react';
import { Input,Button,List } from 'antd';
import 'antd/dist/antd.css';
class TodoListUI extends Component {
render(){
return (
<div style={{marginTop:'10px',marginLeft:'10px'}}>
<div>
<Input onChange={this.props.handleInputChange} placeholder={this.props.inputValue} style={{width:'300px',marginLeft:'10px',marginTop:'10px'}} />
<Button onClick={this.props.handleAddItem} type="primary" style={{marginLeft:'10px',marginTop:'10px'}} >提交</Button>
</div>
<List style={{marginLeft:'10px',marginTop:'10px',width:'300px'}}
bordered
dataSource={this.props.list}
renderItem={(item,index) => (<List.Item onClick={(index) => this.props.handleDeleteItem(index)}>{item}</List.Item> )}
/>
</div>
);
}
}
export default TodoListUI;
2、无状态组件
- 无状态组件就是一个函数。当一个普通的组件只有render函数的时候,可以用无状态组件替换普通组件,以提升性能。
code demo 问题删除时:存在props不是一个函数异常,后面处理。
import React from 'react';
import { Input,Button,List } from 'antd';
import 'antd/dist/antd.css';
const TodoListUI = (props) => {
return (
<div style={{marginTop:'10px',marginLeft:'10px'}}>
<div>
<Input onChange={props.handleInputChange} placeholder={props.inputValue} style={{width:'300px',marginLeft:'10px',marginTop:'10px'}} />
<Button onClick={props.handleAddItem} type="primary" style={{marginLeft:'10px',marginTop:'10px'}} >提交</Button>
</div>
<List style={{marginLeft:'10px',marginTop:'10px',width:'300px'}}
bordered
dataSource={props.list}
renderItem={(item,index) => (<List.Item onClick={ (index) => props.handleDeleteItem(index)}>{item}</List.Item> )}
/>
</div>
);
}
export default TodoListUI;
3、使用Redux-thunk中间件实现异步请求
- 当不使用中间件thunk的时候,action必须是一个对象,当使用thunk后action可以是对象、函数,这样我们就可以在对象中做异步操作等。实际上store只能接受一个对象,不过 store发现action 传过来的是函数的时候,会自动执行这个action函数.
在这个函数里我们会再次定义一个action,并派发此action,此时的action为对象。这个时候store识别出了此对象则进行接收从而改变原始状态。 - 好处:可以把复杂的异步数据处理从组件的生命周期里摘除出来,避免组件过于庞大,方便后期维护、测试。
- https://github.com/zalmoxisus/redux-devtools-extension
- https://github.com/reduxjs/redux-thunk
code demo
- 安装redux-thunk中间件 npm install redux-thunk
- store里高级设置引入中间件,参考官方说明,核心代码如下
import {createStore,applyMiddleware,compose} from 'redux';
import reducer from './reducer';
import thunk from 'redux-thunk';
const composeEnhancers =
typeof window === 'object' &&
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ?
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({
}) : compose;
const enhancer = composeEnhancers(
applyMiddleware(thunk),
);
const store = createStore(reducer, enhancer);
export default store;
3) TodoList.js store可以支持函数,异步改造为
componentDidMount() {
const action = getTodoList();
store.dispatch(action);
}
4)actionCreator.js
export const initListAction = (data) => ({
type: INIT_LIST_ACTION,
data
});
export const getTodoList = () => {
return (dispatch) => {
axios.get('/list.json').then((res) => {
const data = res.data;
const action = initListAction(data);
dispatch(action);
})
}
};
4、Redux-saga中间件的使用
- https://github.com/redux-saga/redux-saga
- 安装 npm install --save redux-saga 或 yarn add redux-saga
- 与thunk的异同
redu-thunk解决异步代码的问题。把异步代码都放到了action,利于自动化测试,以及代码的拆分管理。
redux-saga同样是作异步代码拆分的中间件,可以使用redux-saga完全代替redux-thunk。
引入redux-saga的区别:默认不引入store.dispatch(action); 会在reducer里通过if(action.type === Init_List){}来监听action的执行。引入redux-sage:saga.js的todoSage也可以接收 store.dispatch(action) dispath请求;