来自官网中的一段代码,入下:
// 通过该方法将props传递到父类的构造函数中
constructor(props) {
super(props);
this.state = {date: new Date()};
}
为什么调用super
这并不是 react 的限制,是 js(ES6) 的限制,ES6中 class 的 this 指向问题,ES6中类的继承需要先调用拿到当前实例的 this,然后再用子类的构造函数修改this,如 this.state = ***
。
为什么要传递props
你可能会认为必须给 super
传递 props
,否则 React.Component
就没有办法初始化 this.props
:
class Component {
constructor(props) {
this.props = props;
// ...
}
}
不过,事实证明,如果你漏掉了 props
,直接调用了 super()
,你仍然可以在 render
中或者其他方法中来访问 this.props
。
为什么呢?因为 React在构造函数被调用之后,会把props赋值给刚刚创建的实例对象
const instance = new MyComponent(props);
instance.props = props;
// 可见props不传能用也是有原因的噢
那这样就能以为这可以用 super()
来代替 super(props)
吗? 当然是不可以的,虽然react在构造函数运行之后,给 this.props
赋值了,但是super()
调用之后与构造函数之前, this.props
还是不可以用的。
// 正确的写法
class Component {
constructor(props) {
this.props = props;
// ...
}
}
// 漏掉props的写法
class Component {
constructor(props) {
super(); // 没有传递 props
console.log(props); // 正确,可以打印出来
console.log(this.props); // undefined,
}
}
可见,要是在 super
中漏掉了 props
,在构造函数中访问 this.props
时就会出问题了,因此强烈建议Class 组件应该始终使用 props 参数来调用父类的构造函数,始终写为 super(props);
:
class Component {
constructor(props) {
super(props);
console.log(props); // 正确,可以打印出来
console.log(this.props); // 正确,this.props 始终是有值的
}
}
如果想避免该问题,可以使用 class属性提案 来简化代码:
class Clock extends React.Component {
constructor(props) {
super(props);
this.state = {date: new Date()};
}
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
</div>
);
}
}