react 组件简单实例 — todoList

前言:该实例只是一个简单的react组件化实例,其中有一些写法是便于更好的理解,但在实际情况中可能并不会这样做。会在文章最后做一个总结。

一、效果

二、组件的拆分  ==>> 这里为了突出组件化的思想,把这个小demo拆成了好几个组件(实际项目中可能并不需要,因为比较需求简单)

三、具体代码实现

1. App组件 => index.js

import React, {Component} from 'react';

import './todo.css'
import Lists from './lists'
import Add from './add'

export default class App extends Component{
    // constructor(prop){
    //     super(prop);
    //     this.state = {
    //         commentList: [
    //             {
    //                 name: 'Tom',
    //                 content: 'Hello React!'
    //             },
    //             {
    //                 name: 'Blob',
    //                 content: 'React好难啊!'
    //             },
    //         ]
    //     }
    // }

    state = {           //state可以直接写在组件内部,不要写在constructor构造函数内(简写方式)
        commentList: [
            {
                name: 'Tom',
                content: 'Hello React!'
            },
            {
                name: 'Blob',
                content: 'React好难啊!'
            },
        ]
    };

    addItem = (comment) => {        //新增一条评论,作为回调函数传到add这个子组件中
        const {commentList} = this.state;

        commentList.unshift(comment);
        this.setState({
            commentList: commentList
        })
    };
    delItem = (index) => {           //删除一条评论,作为回调函数传到ListItem这个子组件中
        const {commentList} = this.state;

        commentList.splice(index, 1);
        this.setState({
            commentList: commentList
        })
    };
    render () {
        const {commentList} = this.state;
        return(
            <div>
                <div className='titleBox'>
                    <h2>请发表您对React的看法</h2>
                </div>
                <div className='commentBox'>
                    <Add addItemFun={this.addItem} />
                    <Lists commentList={commentList} delItemFun={this.delItem} />
                </div>
            </div>
        )
    }
}

2. Add组件 => add.js

import React, {Component} from 'react';
import PropTypes from 'prop-types';

import './todo.css'

export default class Add extends Component{
    static proTypes: {
        addItemFun: PropTypes.func.isRequired,
    }
    constructor(){
        super();
        this.state = {
            name: '',
            content: '',
        }
    }

    changeName = (event) => {
        this.setState({
            name: event.target.value,
        })
    };
    changeContent = (event) => {
        this.setState({
            content: event.target.value,
        })
    };

    addComment = () => {
        console.log(this);          //不用箭头函数this为undefined
        const {name, content} = this.state;
        if(name === ''){
            alert('请先填写用户名');
        }else if(content === ''){
            alert('请先填写评论内容');
        }else{
            this.props.addItemFun(this.state)           //调用回调函数把输入的内容传到父组件进行操作
            this.setState({
                name: '',
                content: '',
            })
        }
    };
    render(){
        return(
            <div className='addBox'>
                <p className='userInfo'>
                    <span>用户名:</span>
                    <input className='userName' type='text' value={this.state.name} onChange={this.changeName} />
                </p>
                <p className='userInfo'>
                    <span>评论:</span>
                    <textarea className='content' type='text' value={this.state.content} onChange={this.changeContent} />
                </p>
                <button className='sumbitBtn' onClick={this.addComment}>发布</button>
            </div>
        )
    }
}

3. Lists组件 => lists.js

import React, {Component} from 'react';
import PropTypes from 'prop-types';

import ListItem from './listItem'

export default class Lists extends Component{
    static proTypes = {
        commentList : PropTypes.array.isRequired,
        delItemFun: PropTypes.func.isRequired,
    }

    render() {
        const {commentList, delItemFun} = this.props;
        return(
            <div className='commentList'>
                <h3>评论列表:</h3>
                <h4 style={{display: commentList.length ? 'none' : 'block'}}>暂无评论,点击左侧添加评论!!!</h4>

                {
                    commentList.map((item,index) => {
                        return (<ListItem commentItem={item} key={index} index={index} delItemFun={delItemFun} />)
                    })
                }
            </div>
        )
    }
}

4. ListItem组件 => listItem.js

import React, {Component} from 'react';
import PropTypes from 'prop-types';

export default class ListItem extends Component{
    static propTypes = {
        commentItem: PropTypes.object.isRequired,
        index: PropTypes.number.isRequired,
        delItemFun: PropTypes.func.isRequired,
    };

    delComment = () => {
        const {delItemFun, index} = this.props;
        delItemFun(index)
    };
    render(){
        return(
            <div className='itemBox'>
                <p>{this.props.commentItem.name}说:</p>
                <p>{this.props.commentItem.content}</p>

                <p className='delBtn' onClick={this.delComment}>删除</p>
            </div>
        )
    }
}

5. 样式 => todo.css

.titleBox{
    background: #F0F0F0;
    padding: 60px 20px 20px 20px;
}
.commentBox{
    margin: 0 20px;
    display: flex;
}


/*添加评论 add.js*/
.addBox{
    flex: 1;
}
.userInfo{
    display: flex;
    flex-direction: column;
}
.userName, .content{
    border: solid 1px #ccc;
    height: 24px;
    width: 80%;
    border-radius: 4px;
    padding: 4px;
}
.content{
    height: 100px;
}
.sumbitBtn{
    border-radius: 4px;
    float: right;
    margin-right: 20%;
}
.sumbitBtn:after{
    width: 0;
    height: 0;
    clear: both;
}

/*评论列表*/
.commentList{
    flex: 1;
}
.commentList > h3{
    margin-bottom: 6px;
}

/*评论item*/
.itemBox{
    border: solid 1px #ccc;
    border-radius: 4px;
    margin-bottom: 6px;
    padding: 16px;
    position: relative;
}
.itemBox > p{
    margin: 2px 0;
}
.itemBox > p:nth-child(2){
    text-indent: 30px;
}
.delBtn{
    position: absolute;
    right: 10px;
    top: 5px;
    font-size: 10px;
    border: solid 1px #ccc;
    padding: 2px 6px;
    border-radius: 4px;
    color: #7D9FD1;
    cursor: pointer;
}

6. 使用组件 => 项目的入口文件 index.js

import React from 'react';
import ReactDOM from 'react-dom';
// import App from './App';
import App from './pages/todoList/index';

ReactDOM.render(<App />, document.getElementById('root'));

 

四、总结

1. state的简写方式 => 可以直接写在组件内部,不用写在constructor构造函数内

2. static => 在组件内部使用可以访问到组件类对象,一般用于props的限制(这样不用在组件外部写propTypes)

3. 事件绑定 => 相当于一个回调函数,必须传入一个函数(不能马上调用),如:onClick={this.addComment}

        addComment定义的函数里面的this是undefined,必须使用箭头函数定义或者在constructor中将this执行组件实例

        addComment 使用箭头函数定义,在绑定箭头的时候不能加()传参,这样会立即调用。但有一个默认参数 event ,即绑                    定事件的元素(事件源)

        事件绑定最好的方法是在时间绑定是使用箭头函数或者bind(this)  ==> 可以传参

                箭头函数方式: onClick={ () => this.addComment() }  或者 onClick={ () => { this.addComment() } }

                                           ==> 注意: 箭头函数 () => this.addComment() ,这样是相当于一个函数定义(没有调用)

                                           ==> 函数体不用大括号: 默认返回结果;函数体如果有多个语句, 需要用{}包围,若有需要返回的内容,需要手动返回

                bind(this) 方式:onClick={ this.addComment.bind(this) }  ==> bind(this) 默认返回的是函数体,并且不会调用

                

文章仅为本人学习过程的一个记录,仅供参考,如有问题,欢迎指出!

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值