react.js 将TodoList拆分成一个个组件

TodoList.js

import React, { Component, Fragment } from 'react';
import ToDoItem from './ToDoItem';
import Test from './Test';

class ToDoList extends Component {
    constructor(props) {
        //constructor是一个构造函数,每个类都有,是最先被执行的函数
        super(props)
        //super(props)指的是要调用父类的构造函数
        this.state = {
            //this.state指的是父类的状态
            inputValue: '',//input框的内容
            list: [],//展示的列表
        }
        //当组件的state或者props发生改变的时候,render函数就会重新执行

        this.handleItemDelete = this.handleItemDelete.bind(this)
        this.handleInputChange = this.handleInputChange.bind(this)
        this.handleButtonChange = this.handleButtonChange.bind(this)
        //性能优化
    }
    //输入框的值发生变化
    handleInputChange = (e) => {
        // //输入框第一种获取dom的方法
        // const value = e.target.value
        // // this.setState(() => {
        // //     return {
        // //         inputValue: value
        // //     }
        // // })
        // this.setState(() => ({ inputValue: value }))
        // //新版的react的setState可以接收一个函数,返回一个对象
        // //在ES6里面直接返回一个对象,可以不用return,用()

        //输入框第二种获取dom的方法,使用ref,不建议使用
        const value = this.input.value
        this.setState(() => ({ inputValue: value }))

    }
    //点击提交
    handleButtonChange = () => {
        const { list, inputValue } = this.state
        const newList = [...list, inputValue]
        this.setState(() => (
            {
                list: newList,
                inputValue: ''
            }
        ),()=>{
            console.log(this.ul.querySelectorAll('div').length)
            //查看ul下div的长度
        })
        //this.setState是一个异步函数
    }
    //点击内容(删除)
    handleItemDelete = (index) => {
        this.setState((prevState) => {
            const list = [...prevState.list]//拷贝
            list.splice(index, 1)
            return { list }
        })
        //setState接受的函数,有一个参数是prevState,表示修改前的state值
    }
    getToDoItem = () => {
        return this.state.list.map((item, index) => {
            return (
                <div key={index}>
                    <ToDoItem
                        content={item}
                        index={index}
                        handleItemDelete={this.handleItemDelete}
                    />
                    {/* 父组件向子组件传递内容用属性来传递,子组件通过this.props来获取 */}
                </div>
            )
        })

    }
    render() {
        const { inputValue } = this.state
        return (
            <Fragment>
                {/* Fragment占位符,可以让最外层的div隐藏掉 */}
                <div>
                    <label htmlFor='insertArea'>输入内容</label>
                    {/* 当label被点击时,浏览器会自动将焦点转移到个label相关的input上 */}
                    <input id="insertArea"
                        value={inputValue}
                        onChange={this.handleInputChange}
                        ref={(input) => { this.input = input }}>
                    </input>
                    {/* input框的值和状态中的inputValue进行绑定 */}
                    {/* ref里面的函数会自动接收一个参数,就是input */}
                    <button onClick={this.handleButtonChange}>提交</button>
                    <ul ref={(ul)=>{this.ul = ul}}>{this.getToDoItem()}</ul>
                    <Test content={inputValue} />
                </div>
            </Fragment>
        )
    }
}

export default ToDoList;

ToDoItem.js

import React, { Component } from 'react';

class ToDoItem extends Component {
    constructor(props) {
        super(props);
        this.handleClick = this.handleClick.bind(this)
        //性能优化
    }
    shouldComponentUpdate(nextProps,nextState){
        if(nextProps.content !== this.props.content){
            return true
        }else{
            return false
        }
    }
    //性能优化,因为父组件每次改变state都会render,导致子组件也会render一遍,这里就判断父组件render的时候
    //是否导致content参数发生改变,如果不变,就不render子组件
    //nextProps表示的是Props接下来变化成的样子
    handleClick = () => {
        //点击删除,调用父组件的方法
        const { handleItemDelete, index } = this.props
        handleItemDelete(index)
    }
    render() {
        const { content } = this.props
        return (
            <div onClick={this.handleClick}>{content}</div>
        )
    }
}
export default ToDoItem

Test.js

import React, { Component } from 'react'

class Test extends Component {
    //当父组件的render函数被运行时,它的子组件的render都将重新运行
    render() {
        return <div>{this.props.content}</div>
    }
}
export default Test

猜你喜欢

转载自blog.csdn.net/weixin_44745920/article/details/109591399