React——组合components

1.创建Boxes组件
Boxes组件中包含一系列Box组件。
之前已经写好了一个box.js文件,里面有一个Box类,这个类就可以引入到Boxes.js文件作为一个标签使用。
box.js

import React, { Component } from 'react';

class Box extends Component {
    state = {
        x : 0,
    } 

    handleClickLeft = (step) => {
        this.setState({
            x : this.state.x - step,
        });
    }

    handleClickRight = (step) => {
        this.setState({
            x:this.state.x + step
        });
    }

    render() { 
        return (
            <React.Fragment>
                <div style = {this.getStyle()}>{this.toString()}</div>
                <button onClick={ () => this.handleClickLeft(10)} className="btn btn-warning m-2">left</button>
                <button onClick={() => this.handleClickRight(10)} className='btn btn-secondary m-2'>right</button>
            </React.Fragment>
        );
    }

    getStyle(){
        let style={
            width:"50px",
            height:"50px",
            backgroundColor:"lightblue ",
            color:"white",
            textAlign:"center",
            lineHeight:"50px",
            borderRadius:"5px",
            marginLeft: this.state.x //随着x的变化,方块的位置也会移动
        }
        if(this.state.x === 0) style.backgroundColor="orange";

        return style;
    };

    toString(){
        return "x:"+ this.state.x;
    }
}
 
export default Box;

在这里插入图片描述
boxes.js

import React, { Component } from 'react';
import Box from './box'

class Boxes extends Component {
    state = {  
        boxes: [
            {id: 1, x: 0},
            {id: 2, x: 0},
            {id: 3, x: 0},
            {id: 4, x: 0},
        ]
    } 
    render() { 
        return (
            <React.Fragment>
               {this.state.boxes.map(box => (
                    <Box key={box.id}/>
               ))};
            </React.Fragment>
        );
    }
}
 
export default Boxes;

在这里插入图片描述

2.从上往下传递数据
通过this.props属性可以从上到下传递数据。
通过标签传数据,在标签内定义之后,在定义标签的类里通过this.props可以得到定义的数据,定义时对应的值要加大括号
例如:
boxes.js

render() { 
        return (
            <React.Fragment>
               {this.state.boxes.map(box => (
                    <Box 
                    key={box.id}
                    x = {2}
                    box
                    />
               ))};
            </React.Fragment>
        );
    }

box.js

render() {
        console.log(this.props) ;
        return (
            <React.Fragment>
                <div style = {this.getStyle()}>{this.toString()}</div>
                <button onClick={ () => this.handleClickLeft(10)} className="btn btn-warning m-2">left</button>
                <button onClick={() => this.handleClickRight(10)} className='btn btn-secondary m-2'>right</button>
            </React.Fragment>
        );
    }

输出:
在这里插入图片描述
3.传递子节点
通过this.props.children属性传递子节点
如果是标签嵌套,那么标签内部的孩子也会传递过去
例如:
box.js

render() {
        console.log(this.props) ;
        return (
            <React.Fragment>
                {this.props.children} //调用子节点
                <div style = {this.getStyle()}>{this.toString()}</div>
                <button onClick={ () => this.handleClickLeft(10)} className="btn btn-warning m-2">left</button>
                <button onClick={() => this.handleClickRight(10)} className='btn btn-secondary m-2'>right</button>
            </React.Fragment>
        );
    }

boxes.js

render() { 
        return (
            <React.Fragment>
               {this.state.boxes.map(box => (
                    <Box 
                    key={box.id}
                    x = {box.x}
                    box
                    >
                        <h1>Box:</h1> //子节点
                        <p>#{box.id}</p> //子节点
                    </Box>
               ))};
            </React.Fragment>
        );
    }

输出:
在这里插入图片描述
在这里插入图片描述

并且,如果有多个子节点,可以通过下标来获取某个子节点,第一个下标为0(this.props.children[0]),以此类推

Box在Boxes里面作为标签,也是Boxes的子节点,如果想在Box里面调用上层结点Box的函数,利用3.传递子节点,将父节点的函数作为参数传递给子节点,然后子节点通过this.props.函数名调用。
例如:
box.jsx

render() {
        //console.log(this.props) ;
        return (
            <React.Fragment>
                <div style = {this.getStyle()}>{this.toString()}</div>
                <button onClick={ () => this.handleClickLeft(10)} className="btn btn-warning m-2">left</button>
                <button onClick={() => this.handleClickRight(10)} className='btn btn-secondary m-2'>right</button>
                <button onClick={() => this.props.delete(this.props.id)} className='btn btn-danger m-2'>delete</button> //通过参数调用函数 因为要传参,所以使用匿名函数
            </React.Fragment>
        );
    }

boxes.jsx

handleDelete = (boxId) => {
        const boxes = this.state.boxes.filter(
            b => b.id !== boxId
        );
        this.setState({boxes});
    }

    render() { 
        return (
            <React.Fragment>
               {this.state.boxes.map(box => (
                    <Box 
                    key={box.id}
                    x = {box.x}
                    delete = {this.handleDelete}
                    id = {box.id}
                    />
               ))};
            </React.Fragment>
        );
    }

4.从下往上调用函数
注意:每个组件的this.state只能在组件内部修改,不能在其他组件内修改。
比如box和boxes里面都有一个state.x,如果想在boxes修改box里面的state.x,是不可行的,想要修改的方法就是值保留一个state,保留boxes的state,然后将state作为参数从boxes传递给box使用即可

5.每个维护的数据仅能保存在一个this.state中
不要直接修改this.state的值,因为setState函数可能会将修改覆盖掉。
6.创建App组件
包含:

导航栏组件
Boxes组件

注意:

要将多个组件共用的数据存放到最近公共祖先的this.state中。

App组件里面有导航栏组件和Boxes组件,如果想在导航栏组件和Boxes组件之间互传信息,就必须将公共信息放在App组件里,这样可以通过向子节点传参的方式传给两个子节点组件
比如要NavBar组件传state.boxes的元素个数,给Boxes组件传state.boxes和所有的方法
因为两个组件共用state,所以state放在App里

render() { 
        return (
            <React.Fragment>
                <NavBar boxes={this.state.boxes.length}/>
                <div className="container">
                <Boxes 
                    boxes = {this.state.boxes}
                    onReset={this.handleReset}
                    onClickLeft={this.handleClickLeft}
                    onClickRight={this.handleClickRight}
                    onDelete={this.handleDelete}
                />
                </div>
                
            </React.Fragment>

        );
    }

7.无状态函数组件
当组件中没有用到this.state时,可以简写为无状态的函数组件。
函数的传入参数为props对象
修改前:
boxes.js

import React, { Component } from 'react';
import Box from './box'

class Boxes extends Component {
    
    render() { 
        return (
            <React.Fragment>
                <button 
                onClick={this.props.onReset}
                style={{marginBottom: "15px"}} className='btn btn-danger'>Reset</button>
               {this.props.boxes.map(box => (
                    <Box 
                    key={box.id}
                    box = {box}
                    clickLeft = {() => this.props.onClickLeft(box)}
                    clickRight = {() => this.props.onClickRight(box)}
                    delete = {this.props.onDelete}
                    />
               ))};
            </React.Fragment>
        );
    }
}
 
export default Boxes;

修改为无函数组件后:
其实就是将原来render()函数里面的return…复制到Boxes里面,将所有的this去掉
boxes.js

import React, { Component } from 'react';
import Box from './box'
const Boxes = (props) => {
    return (
        <React.Fragment>
            <button 
            onClick={props.onReset}
            style={{marginBottom: "15px"}} className='btn btn-danger'>Reset</button>
           {props.boxes.map(box => (
                <Box 
                key={box.id}
                box = {box}
                clickLeft = {() => props.onClickLeft(box)}
                clickRight = {() => props.onClickRight(box)}
                delete = {props.onDelete}
                />
           ))};
        </React.Fragment>
    );
}
 
export default Boxes;

8.组件的生命周期

Mount周期,执行顺序:constructor() -> render() -> componentDidMount()
Update周期,执行顺序:render() -> componentDidUpdate()
Unmount周期,执行顺序:componentWillUnmount()

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值