UI组件:只负责页面的渲染功能,也称为傻瓜组件;
容器组件:只负责业务逻辑和数据的处理,也称为聪明组件;
无状态组件:把UI组件用函数表示(可以省去生命周期函数,优化代码)
组件如何渲染由render
函数决定,当逻辑和渲染都写在一个组件中,给维护带来很大的困难,这是可以将组件进行拆分,让UI组件
单独负责页面渲染的功能(只包含render
函数),让容器组件
负责逻辑,在容器组件中引入UI组件
进行渲染即可,这样可以使代码更加精简
1、普通组件:
import React ,{Component}from 'react';
import 'antd/dist/antd.css'
import {Input,Button,List} from 'antd'
import store from './store/index';
import {getInputChangeAction,getAddItemActiom,getDeleteItemAction}from './store/actionCreator';
class TodoList extends Component{
constructor(props){
super(props);
this.state=store.getState();
store.subscribe(this.handleStoreChange)
}
render(){
return(
<div style={{margin:'10px',marginLeft:'10px'}}>
<div>
<Input
value={this.state.inputValue}
placehoder="todo list "
style={{width:'300px'}}
onChange={this.handleInputChange}
/>
<Button
type= "primary"
onClick={this.handleBtnClick}
>提交</Button>
</div>
<List
style={{marginTop:'10px',width:'300px'}}
bordered
dataSource={this.state.list}
renderItem={(item,index) => (<List.Item onClick={this.handleItemDelet} >{item}</List.Item>)}//这个这个参考antd官网
/>
</div>
)
}
handleInputChange=(e)=>{
const action=getInputChangeAction(e.target.value);
store.dispatch(action);
};
handleStoreChange=()=>{
this.setState(store.getState());
};
handleBtnClick=()=>{
const action=getAddItemActiom();
store.dispatch(action);
};
handleItemDelet=(index)=>{
const action=getDeleteItemAction(index);
store.dispatch(action);
}
}
export default TodoList;
上面的代码给我们最直观的感受是什么?维护性差!是的在一个组件中既有UI又有逻辑,这是很不利于测试和维护的,因为我们很不容易弄明白如果这个组件出现问题的了,是UI部分出现问题还是逻辑部分出现问题!所以,聪明的办法就是把逻辑和UI进行分离,UI组件专门用来渲染页面,逻辑组件专门用来逻辑处理!那么问题来了,我们怎么去进行拆分呢?相信大家对组件怎么传递方法和状态的方法已经很熟悉了,下面我们把刚刚的TodoList产分为Todolist和TodulistUI两个组件:
2、普通组件拆分成之一TodoListUi.js(UI组件)
import React ,{Component}from 'react';
import 'antd/dist/antd.css'
import {Input,Button,List} from 'antd'
class TodoListUi extends Component{
render(){
return(
<div style={{margin:'10px',marginLeft:'10px'}}>
<div>
<Input
value={this.props.inputValue}
placehoder="todo list "
style={{width:'300px'}}
onChange={this.props.handleInputChange}
/>
<Button
type= "primary"
onClick={this.props.handleBtnClick}
>提交</Button>
</div>
<List
style={{marginTop:'10px',width:'300px'}}
bordered
dataSource={this.props.list}
renderItem={(item,index) => (<List.Item onClick={(index)=>{this.props.handleItemDelet(index)}} >{item}</List.Item>)}
//调用父组件带参数的函数用箭头函数
/>
</div>
)
}
}
export default TodoListUi;
3、普通组件拆分成之二TodoList.js(容器组件)
import React ,{Component}from 'react';
import store from './store/index';
import {getInputChangeAction,getAddItemActiom,getDeleteItemAction}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
inputValue={this.state.inputValue}
list={this.state.list}
handleInputChange={this.handleInputChange}
handleBtnClick={this.handleBtnClick}
handleItemDelet={this.handleItemDelet}
/>
)
}
handleInputChange=(e)=>{
const action=getInputChangeAction(e.target.value);
store.dispatch(action);
};
handleStoreChange=()=>{
this.setState(store.getState())
};
handleBtnClick=()=>{
const action=getAddItemActiom();
store.dispatch(action);
};
handleItemDelet=(index)=>{
const action=getDeleteItemAction(index);
store.dispatch(action);
}
}
export default TodoLis;
看上面UI组件的代码,可以发现该组件中只有一个render函数,当一个组件中只有一个render函数时,就可以将这个组件定义为一个无状态组件:
其实无状态组件就是一个函数式组件。
无状态组件的优势:
无状态组件的性能要高,无状态组件就是一个函数,而类组件时js中的一个类,类生成的对象中有一些生命周期函数,类组件运行时,既要执行生命周期函数,又要执行render函数,所以性能要比无状态函数要低。
4、UI组件TodoListUi.js把类换成函数(无状态组件)
import React ,{Component}from 'react';
import 'antd/dist/antd.css'
import {Input,Button,List} from 'antd'
const TodoListUi=(props)=>{//无状态组件就是一个函数,接受一个props参数(
//父组件传递过来的内容),返回一个JSX
return(
<div style={{margin:'10px',marginLeft:'10px'}}>
<div>
<Input
value={props.inputValue}
placehoder="todo list "
style={{width:'300px'}}
onChange={props.handleInputChange}
/>
<Button
type= "primary"
onClick={props.handleBtnClick}
>提交</Button>
</div>
<List
style={{marginTop:'10px',width:'300px'}}
bordered
dataSource={props.list}
renderItem={(item,index) => (<List.Item onClick={()=>{
props.handleItemDelet(index)}} >{item}</List.Item>)}
//调用父组件带参数的函数用箭头函数
/>
</div>
)
};
export default TodoListUi;
其他相关代码:
抽取的action:
actionCreators.js
import { CHANGE_INPUT_VALUE, ADD_TODO_ITEM, DELETE_TODO_ITEM, INIT_LIST_ACTION } from './actionTypes'
export const getInputChangeAction = (value) => ({
typt:CHANGE_INPUT_VALUE,
value
});
export const getAddItemAction = () => ({
typt:ADD_TODO_ITEM,
});
export const getDeleteItemAction = (index) => ({
typt:DELETE_TODO_ITEM,
index
});
export const initListAction = (data) => ({
typt:INIT_LIST_ACTION,
data
});
actionTypes.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';
export const INIT_LIST_ACTION = 'init_list_action';