浅析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()