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

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

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

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

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()};
這時你會發(fā)現(xiàn)super(props)是什么鬼?我注釋掉行不行?答案是不行的。你會看到下面這段鮮紅的BUG。

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

super關(guān)鍵字,它指代父類的實例(即父類的this對象)。子類必須在constructor方法中調(diào)用super方法,否則新建實例時會報錯。這是因為子類沒有自己的this對象,而是繼承父類的this對象,然后對其進行加工。如果不調(diào)用super方法,子類就得不到this對象。

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

雖然 React 會在組件實例化的時候設(shè)置一遍 props(當(dāng)React添加對類的支持時,它不僅僅增加了對ES6類的支持。目標是盡可能支持廣泛的類抽象。目前尚不清楚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ù)初始化時都用super(props)

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

如果沒用到constructor,是可以不寫的;React會默認添加一個空的constructor。

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

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

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





作者:Vam的金豆之路

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

我的微信:maomin9761

微信公眾號:前端歷劫之路