UI组件与容器组件的拆分以及无状态组件优化(五)

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';

猜你喜欢

转载自blog.csdn.net/qq_38277366/article/details/82924348
今日推荐