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):前端歷劫之路