React关于constructor与super(props)之间的相爱相杀

我们先把菜鸟教程的一段代码拿过来分析一下。下面这段代码是用了将生命周期方法添加到类中实现时钟效果。

// 将生命周期方法添加到类中
class Clock extends React.Component {
  constructor(props) {
    super(props);
    this.state = {date: new Date()};//初始化
  }
//开始
  componentDidMount() {
     this.timerID = setInterval(
       () => this.tick(),
       1000
     );
   }
//销毁
   componentWillUnmount() {
     clearInterval(this.timerID);
   }
//重新改变date值
   tick() {
     this.setState({
       date: new Date()
     });
   }
//注册组件
  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <h2>现在是 {this.state.date.toLocaleTimeString()}.</h2>
      </div>
    );
  }
}
//····································
//挂载到实例
ReactDOM.render(
  <Clock />,
  document.getElementById('example')
);

好,下面我们就再写一段原生js实现上述效果,对比一下。

function timejs () {
  this.timer = null;
  var time1= new Date();
  var time2=time1.toLocaleTimeString()
  document.getElementById("time").innerHTML = time2  //这里的id为time我这里没写,自己写上即可<div id='time'></div> 
}
var timer=setInterval(timejs,1000);

嗯,我们可以看到原生js代码量比React少得多。
下面我们为了方便起见。将React中的代码写为A,将原生JS中的代码写为B。
B中的timejs()相当于A中的tick(),不同的是A需要初始化,所以A中有 this.state = {date: new Date()};
这时你会发现super(props)是什么鬼?我注释掉行不行?答案是不行的。你会看到下面这段鲜红的BUG。

在这里插入图片描述
错误的含义是this之前不能没有super(props)
那么super到底是什么呢

super关键字,它指代父类的实例(即父类的this对象)。子类必须在constructor方法中调用super方法,否则新建实例时会报错。这是因为子类没有自己的this对象,而是继承父类的this对象,然后对其进行加工。如果不调用super方法,子类就得不到this对象。

简言之,如果你想在constructor中使用this,就必须用super(props),
那么在这里可以不传props吗?答案是最好写。

虽然 React 会在组件实例化的时候设置一遍 props(当React添加对类的支持时,它不仅仅增加了对ES6类的支持。目标是尽可能支持广泛的类抽象。目前尚不清楚ClojureScript,CoffeeScript,ES6,Fable,Scala.js,TypeScript或其他解决方案在定义组件方面的成功程度。所以React故意不关心是否需要调用super - 即使是ES6类。),但在 super 调用一直到构造函数结束之前,this.props 依然是未定义的。
执行 super(props) 可以使基类 React.Component 初始化 this.props。
好,我把代码改了改

// 将生命周期方法添加到类中
class Clock extends React.Component {
  constructor(props) {
    super(props);
    console.log(this.props)
    this.state = {
      date: new Date(),
      tit:'success'
    };//初始化
  }

  componentDidMount() {
     this.timerID = setInterval(
       () => this.tick(),
       1000
     );
   }

   componentWillUnmount() {
     clearInterval(this.timerID);
   }

   tick() {
     this.setState({
       date: new Date()
     });
   }



  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <h2>现在是 {this.state.date.toLocaleTimeString()}.</h2>
        <button>{this.props.val}</button>
      </div>
    );
  }
}

ReactDOM.render(
  <Clock val='success'/>,
  document.getElementById('example')
);

总之,你不管用不用this.props。最好在使用constructor构造函数初始化时都用super(props)

如果需要访问this就设置constructor

如果没用到constructor,是可以不写的;React会默认添加一个空的constructor。

如果你用到了constructor就必须写super(),是用来初始化this的,可以绑定事件到this上;

如果你在constructor中要使用this.props,就必须给super加参数:super(props);

无论有没有constructor,在render中this.props都是可以使用的,这是React自动附带的。





作者:Vam的金豆之路

主要领域:前端开发

我的微信:maomin9761

微信公众号:前端历劫之路