• React组件的数据


    React组件的数据分两种,prop和state,prop或state的改变都会引发组件的重新渲染。prop是组件的对外接口,state是组件的内部状态,对外用prop,对内用state。

    React的prop

    当外部世界要传递数据给React组件,最直接的方式就是通过prop;同样,React组件要反馈数据给外部,也可以通过prop。prop的类型不限于纯数据,也可以是函数,函数类型的prop等于父组件传递给子组件一个回调函数,子组件可以对这个回调函数传参,这样就可以把信息传给外部世界。

    // ./lesson2/chapter1/ControlPanel.js
    
    class ControlPanel extends Component {
        constructor() {
            super(...arguments);
            this.handleClick = this.handleClick.bind(this);
        }
        handleClick(name) {
            alert(name)
        }
        render() {
            console.log('enter ControlPanel render');
            return (
                <div style={style}>
                    <Counter caption="First" handleClick={this.handleClick}/>
                </div>
            );
        }
    }
    
    //  ./lesson2/chapter1/Counter.js
    
    class Counter extends Component {
        constructor(props) {
          super(props);
          this.handleClick = this.handleClick.bind(this);
        }
        handleClick() {
            this.props.handleClick('点我啊');
        }
        render() {
            const {caption} = this.props;   //  ES6对象结构的写法
            return (
                <div>
                    <button onClick={this.handleClick}>+</button>
                    <span>caption:{caption}</span>
                </div>
            );
        }
    }
    

    读取prop值

    从上面例子可以看到ControlPanel.js中组件Counter传递一个叫作caption的prop,其值为First,又传递了一个叫作handleClick的prop,其值是一个函数。在Counter.js中,通过this.props.caption即可获得caption的值。在Counter组件中,我们给一个button绑定点击事件,调用从父组件传递过来的handleClick函数,并传递一个参数给父组件。

    先回顾一下,在ES6的课程中,关于CLASS的super我们说过以下几点:

    • super()方法可访问基类的构造函数
    • super()只可在派生类的构造函数中调用
    • super()负责初始化this,在构造函数中访问this前要调用super()

    在Counter组件中,我们可以看到:一个组件需要定义自己的构造函数,需要在第一行调用super(props) [constructor中可能还会传入其他参数,也可这样写super(...arguments)];给super()传入props作为参数,则可在构造函数中访问this.props。在构造函数中还给成员函数绑定了当前this的执行环境,ES6方法创造的React组件类并不会自动给我们绑定this到当前对象。

    propTypes检查

    既然prop是组件的对外接口,那么就应该有某种方式让组件申明自己的接口规范。ES6定义的组件类中,可以通过增加类的propTypes属性来定义prop规格。

    比如,对Counter组件的propTypes定义如下代码:

    Counter.propTypes = {
        caption: PropTypes.string.isRequired,
        initValue: PropTypes.number
    }
    

    其中要求caption必须是string类型,initValue必须是number,并且caption的值还是必须存在的。为了验证,可将ControlPanel.js中的render函数增加如下代码

    <Counter caption={123}/>
    

    控制台中可以看到一个红色的提示警告。

    propTypes虽然能够在开发阶段发现代码问题,但在产品环境中并不需要。因为propTypes检查也是要消耗CPU计算资源的。所以最好的方式是,开发环境定义propTypes,生产环境通过babel-react-optimize优化去掉propTypes。关于propTypes具体用法请参见官方文档

    React中的state

    驱动组件渲染过程的除了prop,还有state,state代表组件的内部状态。由于React不能修改传入的prop,所以只能通过修改state来记录自身数据的变化。

    // ./lesson2/chapter2/Counter.js
    class Counter extends Component {
        constructor(props) {
            ... ...
            this.state = {
                count: props.initValue
            }
        }
    
        onClickIncrementButton() {
            this.setState({count: this.state.count + 1});
        }
    
        onClickDecrementButton() {
            this.setState({count: this.state.count - 1});
        }
    
        render() {
            const {caption} = this.props;
            return (
                <div>
                    <button style={buttonStyle} onClick={this.onClickIncrementButton}>+</button>
                    <button style={buttonStyle} onClick={this.onClickDecrementButton}>-</button>
                    <span>{caption} count: {this.state.count}</span>
                </div>
            );
        }
    }
    
    Counter.defaultProps = {
        initValue: 0
    };
    
    export default Counter;
    

    初始化state

    在Counter组件中,我们通过this.state完成对组件state的初始化,代码如下:

    constructor(props) {
        ... ...
        this.state = {
            count: props.initValue || 0
        }
    }
    

    组件的state必须是一个javascript对象。通常情况,我们不会通过state设置初始值,而是通过React的defaultProps的功能。

    constructor(props) {
        ... ...
        this.state = {
            count: props.initValue
        }
    }
    
    Counter.defaultProps = {
        initValue: 0
    };
    

    读取和更新state

    在button上绑定点击事件,通过触发点击的回调函数来改变state值。代码如下:

    onClickIncrementButton() {
        this.setState({count: this.state.count + 1});
    }
    
    
    <button style={buttonStyle} onClick={this.onClickIncrementButton}>+</button>
    

    Tips: 改变state必须通过this.setState(),直接去修改this.state并不会让页面重新渲染。 直接修改this.state的值,虽然改变了组件的内部状态,但只是野蛮的修改state,却没有驱动组件进行重新渲染,既然组件没有重新渲染,当然不会反应this.state值的变化;而this.setState()函数所做的事情,首先是改变this.state的值,然后驱动组件更新,这样才有机会让this.state的新值出现在界面上。

    prop和state的对比

    • prop用于定义外部接口,state用于记录内部状态
    • prop的值通过外部组件传入,state的值在组件内部定义
    • 组件不应该修改prop的值,state存在的目的就是让组件来改变的
  • 相关阅读:
    APP测试-流量测试
    APP测试-流畅度测试
    APP测试-耗电分析
    工具安装-Homebrew
    工具安装-go for Mac
    APP测试-耗电量测试
    APP测试-CPU测试
    APP测试-内存测试
    APP测试-monkey
    APP测试-adb命令
  • 原文地址:https://www.cnblogs.com/renzhiwei2017/p/9439242.html
Copyright © 2020-2023  润新知