React關(guān)于constructor與super(props)之間的相愛相殺

我們先把菜鳥教程的一段代碼拿過來分析一下。下面這段代碼是用了將生命周期方法添加到類中實(shí)現(xiàn)時(shí)鐘效果。

// 將生命周期方法添加到類中
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()
     });
   }
//注冊(cè)組件
  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <h2>現(xiàn)在是 {this.state.date.toLocaleTimeString()}.</h2>
      </div>
    );
  }
}
//····································
//掛載到實(shí)例
ReactDOM.render(
  <Clock />,
  document.getElementById('example')
);

好,下面我們就再寫一段原生js實(shí)現(xiàn)上述效果,對(duì)比一下。

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少得多。
下面我們?yōu)榱朔奖闫鹨?。將React中的代碼寫為A,將原生JS中的代碼寫為B。
B中的timejs()相當(dāng)于A中的tick(),不同的是A需要初始化,所以A中有 this.state = {date: new Date()};
這時(shí)你會(huì)發(fā)現(xiàn)super(props)是什么鬼?我注釋掉行不行?答案是不行的。你會(huì)看到下面這段鮮紅的BUG。

在這里插入圖片描述
錯(cuò)誤的含義是this之前不能沒有super(props)
那么super到底是什么呢

super關(guān)鍵字,它指代父類的實(shí)例(即父類的this對(duì)象)。子類必須在constructor方法中調(diào)用super方法,否則新建實(shí)例時(shí)會(huì)報(bào)錯(cuò)。這是因?yàn)樽宇悰]有自己的this對(duì)象,而是繼承父類的this對(duì)象,然后對(duì)其進(jìn)行加工。如果不調(diào)用super方法,子類就得不到this對(duì)象。

簡言之,如果你想在constructor中使用this,就必須用super(props),
那么在這里可以不傳props嗎?答案是最好寫。

雖然 React 會(huì)在組件實(shí)例化的時(shí)候設(shè)置一遍 props(當(dāng)React添加對(duì)類的支持時(shí),它不僅僅增加了對(duì)ES6類的支持。目標(biāo)是盡可能支持廣泛的類抽象。目前尚不清楚ClojureScript,CoffeeScript,ES6,F(xiàn)able,Scala.js,TypeScript或其他解決方案在定義組件方面的成功程度。所以React故意不關(guān)心是否需要調(diào)用super - 即使是ES6類。),但在 super 調(diào)用一直到構(gòu)造函數(shù)結(jié)束之前,this.props 依然是未定義的。
執(zhí)行 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>現(xiàn)在是 {this.state.date.toLocaleTimeString()}.</h2>
        <button>{this.props.val}</button>
      </div>
    );
  }
}

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

總之,你不管用不用this.props。最好在使用constructor構(gòu)造函數(shù)初始化時(shí)都用super(props)

如果需要訪問this就設(shè)置constructor

如果沒用到constructor,是可以不寫的;React會(huì)默認(rèn)添加一個(gè)空的constructor。

如果你用到了constructor就必須寫super(),是用來初始化this的,可以綁定事件到this上;

如果你在constructor中要使用this.props,就必須給super加參數(shù):super(props);

無論有沒有constructor,在render中this.props都是可以使用的,這是React自動(dòng)附帶的。





作者:Vam的金豆之路

主要領(lǐng)域:前端開發(fā)

我的微信:maomin9761

微信公眾號(hào):前端歷劫之路