浅析React组件constructor、super()、super(props)的区别

一、定义class组件,为什么需要加上 super() ?

  我们尝试去掉 super() 看看编译的结果:

constructor() {
  this.state = {searchStr: ''};
  this.handleChange = this.handleChange.bind(this);
}

  报错编译错误:

  提示少写了super(),导致 Reference Error

二、那 super 的作用究竟是什么?

  super关键字,它指代父类的实例(即父类的this对象)。子类必须在constructor方法中调用super方法,否则新建实例时会报错。

  这是因为子类没有自己的this对象,而是继承父类的this对象,然后对其进行加工。如果不调用super方法,子类就得不到this对象

  正确的姿势是:

constructor() {
  super();
  this.state = {searchStr: ''};
  this.handleChange = this.handleChange.bind(this);
}

  react 官方例子中都是加上了 props 作为参数

constructor(props) {
  super(props);
  this.state = {searchStr: ''};
  this.handleChange = this.handleChange.bind(this);
}

三、加与不加props的区别究竟在哪里?

What’s the difference between “super()” and “super(props)” in React when using es6 classes?

There is only one reason when one needs to pass props to super():

When you want to access this.props in constructor.

  翻译:只有一个理由需要传递props作为super()的参数,那就是你需要在构造函数内使用this.props

四、constructor与super()

  react的组件大部分采用的都是es6的class语法糖写法,而constructor就是class里面的默认方法,是必须的,如果我们没有定义,那么系统会默认生成一个constructor方法。

  而super(),是在constructor里面,用于继承父类的,因为子类是没有自己的this的,需要从父类继承,而super就是子类继承父类的方法。

  简单一点来说,就是你写class类的时候可以不写constructor,系统会默认帮你生成一个。但是你写constructor的时候,就必须要写super(),否则就用不了this。

export default class Test extends Component {
    state = {
        name: "Jack"
    }
    render() {
        return (
            <div>
                {this.state.name}
            </div>
        )
    }
}

  如上面的代码,没有定义constructor,此时代码还是可以正常运行,因为系统默认就帮你定义了一个constructor。它相当于下面的代码:

export default class Test extends Component {
    constructor(){
        super()
    }
    state = {
        name: "123"
    }
    render() {
        return (
            <div>
                {this.state.name}
            </div>
        )
    }
}

  但是,如果如果不写super的话,下面的代码就会报错:

export default class Test extends Component {
    constructor(){
        
    }
    state = {
        name: "123"
    }
    render() {
        return (
            <div>
                {this.state.name}
            </div>
        )
    }
}

  此时会因为找不到this而报错,因为子类没有自己的this。

五、super()与super(props)

  super()与super(props) 区别就是,有没有传入props参数。

  我们都知道,props是父类传递给子类的值,那这是不是意味着要用父类传递给子类的值的时候,就需要传参props呢?答案是不用的,我们来看一下下面的例子。

// 父类
export default class App extends Component {
  return (
    <div className="App">
      <Test name="faName"></Test>
    </div>
  );
}

// 子类
export default class Test extends Component {
    componentDidMount() {
        console.log(this.props)
    }
    render() {
        return (
            <div>
                <div>{this.props.name}</div>
            </div>
        )
    }
}

  此时代码能够顺利运行,页面上也能显示出 faName,而且componentDidMount生命周期,也能够打印出props的值,那么,super(props)的作用的什么呢?

  答案是:在 constructor 函数里面,需要用到props的值的时候,就需要调用 super(props)

export default class Test extends Component {
    constructor(props) {
        super()
        this.state = {
            name: this.props.name
        }
    }
}

  如上面的代码会报错找不到name,因为如果在constructor里,没有调用super(props),是获取不到props的值的。但是这个也仅仅局限于constructor函数,其他生命周期函数,是不受影响的。

六、总结

1、class语法糖默认会帮你定义一个constructor,所以当你不需要使用constructor的时候,是可以不用自己定义的

2、当你自己定义一个constructor的时候,就一定要写super(),否则拿不到this

3、当你在constructor里面想要使用props的值,就需要传入props这个参数给super,调用super(props),否则只需要写super()

posted @ 2017-11-02 09:44  古兰精  阅读(537)  评论(0编辑  收藏  举报