1、this.props在构造器中使用时,需要用super(props)

props是我们React父子组件之间通信的对象,this.props在构造器中使用时,需要用super(props)进行传递。

举例说明,下面这个构造器constructor中是获取不到this.props.msg的值的。

class Welcome extends React.Component {
    constructor(){
        super();
        console.log( this.props.msg )   // undefined
    }
    render(){
        return (
            <div>hello world, {this.props.msg}</div>
        );
    }
}
let element = (
    <Welcome msg="hi react" />
);

可以通过给super()传递props参数是可以做到的,代码如下:

constructor(props){
    super(props);
    console.log( this.props.msg )   // hi react
}

结合起来,也就是这样写:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="../react.development.js"></script>
  <script src="../react-dom.development.js"></script>
  <script src="../babel.min.js"></script>
</head>
<body>
  <div id="app"></div>
  <script type="text/babel">

    let app = document.querySelector('#app');

    let root = ReactDOM.createRoot(app); 
    
    
    class Welcome extends React.Component {
      constructor(props){
        super(props);
        console.log( this.props.msg )
      }
      render(){
        return (
          <div>hello world, {this.props.msg}</div>
        );
      }
    }
    let element = (
      <Welcome msg="hi react" />
    );

    root.render(element); 
    
  </script>
</body>
</html>

那么React类组件是如何设计的呢?就要对面向对象非常的熟悉,原理分析如下:

// 父类
class Foo {
    constructor(props){
        this.props = props;
    }
}
// 子类
class Bar extends Foo {
    constructor(props){
        super(props);
        console.log(this.props);
    }
    render(){
        console.log(this.props);
        return '';
    }
}
let props = {
    msg: 'hello world'
};
let b = new Bar(props);
b.props = props;
b.render();

创建Bar的对象b时,就要将props传进去,这样才能通过super(props)传递到父类的构造器,

上面两行console.log才能正常打印出this.props对象。

2、多属性传递可通过扩展运算符实现

当有非常多的属性要传递的时候,那么会比较麻烦,比如这样时:

let element = (
	<Welcome msg="hi react" username="xiaoming" age={20} />
);

所以可通过扩展运算形式进行简写:

class Welcome extends React.Component {
    render(){
        // 解构
        let { msg, username, age } = this.props;
        return (
            <div>hello world, {msg}, {username}, {age}</div>
        );
    }
}
// 以对象的形式传递
let info = {
    msg: 'hi react',
    username: 'xiaoming',
    age: 20
};
// 使用...扩展运算符来展开info对象的属性和值
let element = (
    <Welcome {...info} />
);

3、props是单向数据流,不能直接修改

像下面这样在render中改props的属性值,会报错

class Welcome extends React.Component {
    render(){
        // 不能对props下的属性进行修改,因为数据是单向流动的
        this.props.msg = 'hello world';
      
        let { msg, username, age } = this.props;
        console.log( isChecked );
        return (
            <div>hello world, {msg}, {username}, {age}</div>
        );
    }
}
let info = {
    msg: 'hi react',
    username: 'xiaoming',
    age: 20
};
let element = (
    <Welcome {...info} />
);

4、给属性限定类型与添加默认值

  • 可以添加一个static对象,添加默认属性值:
class Welcome extends React.Component {
    //给属性添加默认值
    static defaultProps = {
      age: 0
    }
    render(){
        let { msg, username, age } = this.props;
        return (
            <div>hello world, {msg}, {username}, {age}</div>
        );
    }
}

let info = {
    msg: 'hi react',
    username: 'xiaoming',
  	// 如果age的值没有设置,会显示默认值
    //age: 20
};

let element = (
    <Welcome {...info} />
);
  • 对属性的类型进行限制

    需要添加一个prop-types

import PropTypes from 'prop-types'
class Welcome extends React.Component {
    //添加默认值
    static defaultProps = {
        age: 0
    }
    static propTypes = {
      	// 限定为number(如果是字符串则是PropTypes.string)
        age: PropTypes.number
    }
    ...
}

这里的类型需要引入第三方模块才可以生效。

注意,这里是运行时进行限定,不是在编译时进行限定。

5、只有属性名没有值时,默认值为true

当父子通信的时候,如果只写属性,不写值的话,那么对应的值就是布尔值true。

class Welcome extends React.Component {
    render(){
        // 解构
        let { msg, username, age, isChecked } = this.props;
      	// isChecked打印出来是:true
      	console.log( isChecked );
        return (
            <div>hello world, {msg}, {username}, {age}</div>
        );
    }
}
// 以对象的形式传递
let info = {
    msg: 'hi react',
    username: 'xiaoming',
    age: 20
};
// 使用...扩展运算符来展开info对象的属性和值
let element = (
  // isChecked没有给值
  <Welcome {...info} isChecked />
);

上面的isChecked属性没有给值,那么打印出来就是布尔值true。