2020-03-09

在組件的整個生命周期中胆筒,隨著該組件的props或者state發(fā)生改變,其DOM表現(xiàn)也會有相應(yīng)的變化酱酬。一個組件就是一個狀態(tài)機(jī)壶谒,對于特定地輸入,它總返回一致的輸出膳沽。

一個React組件的生命周期分為三個部分:實例化汗菜、存在期和銷毀時。

實例化

當(dāng)組件在客戶端被實例化挑社,第一次被創(chuàng)建時陨界,以下方法依次被調(diào)用:

1、getDefaultProps
2痛阻、getInitialState
3菌瘪、componentWillMount
4、render
5阱当、componentDidMount

當(dāng)組件在服務(wù)端被實例化俏扩,首次被創(chuàng)建時,以下方法依次被調(diào)用:

1弊添、getDefaultProps
2录淡、getInitialState
3、componentWillMount
4油坝、render

componentDidMount 不會在服務(wù)端被渲染的過程中調(diào)用嫉戚。

getDefaultProps

對于每個組件實例來講,這個方法只會調(diào)用一次澈圈,該組件類的所有后續(xù)應(yīng)用彬檀,getDefaultPops 將不會再被調(diào)用,其返回的對象可以用于設(shè)置默認(rèn)的 props(properties的縮寫) 值极舔。

var Hello = React.creatClass({
    getDefaultProps: function(){
        return {
            name: 'pomy',
            git: 'dwqs'
        }
    },

    render: function(){
        return (
            <div>Hello,{this.props.name},git username is {this.props.dwqs}</div>
        )
    }
});

ReactDOM.render(<Hello />, document.body);

也可以在掛載組件的時候設(shè)置 props:

var data = [{title: 'Hello'}];
<Hello data={data} />

或者調(diào)用 setProps (一般不需要調(diào)用)來設(shè)置其 props:

var data = [{title: 'Hello'}];
var Hello = React.render(<Demo />, document.body);
Hello.setProps({data:data});

但只能在子組件或組件樹上調(diào)用 setProps凤覆。別調(diào)用 this.setProps 或者 直接修改 this.props链瓦。將其當(dāng)做只讀數(shù)據(jù)拆魏。

React通過 propTypes 提供了一種驗證 props 的方式,propTypes 是一個配置對象慈俯,用于定義屬性類型:

var survey = React.createClass({
    propTypes: {
        survey: React.PropTypes.shape({
            id: React.PropTypes.number.isRequired
        }).isRequired,
        onClick: React.PropTypes.func,
        name: React.PropTypes.string,
        score: React.PropTypes.array
        ...
    },

    //...
})

組件初始化時渤刃,如果傳遞的屬性和 propTypes 不匹配,則會打印一個 console.warn 日志贴膘。如果是可選配置卖子,可以去掉.isRequired。常用的 PropTypes 如下:

[圖片上傳失敗...(image-9dfed6-1583734909257)]

getInitialState

對于組件的每個實例來說刑峡,這個方法的調(diào)用有且只有一次洋闽,用來初始化每個實例的 state玄柠,在這個方法里,可以訪問組件的 props诫舅。每一個React組件都有自己的 state羽利,其與 props 的區(qū)別在于 state只存在組件的內(nèi)部,props 在所有實例中共享刊懈。

getInitialState 和 getDefaultPops 的調(diào)用是有區(qū)別的这弧,getDefaultPops 是對于組件類來說只調(diào)用一次,后續(xù)該類的應(yīng)用都不會被調(diào)用虚汛,而 getInitialState 是對于每個組件實例來講都會調(diào)用匾浪,并且只調(diào)一次。

var LikeButton = React.createClass({
  getInitialState: function() {
    return {liked: false};
  },
  handleClick: function(event) {
    this.setState({liked: !this.state.liked});
  },
  render: function() {
    var text = this.state.liked ? 'like' : 'haven\'t liked';
    return (
      <p onClick={this.handleClick}>
        You {text} this. Click to toggle.
      </p>
    );
  }
});

ReactDOM.render(
  <LikeButton />,
  document.getElementById('example')
);

每次修改 state卷哩,都會重新渲染組件蛋辈,實例化后通過 state 更新組件,會依次調(diào)用下列方法:

1将谊、shouldComponentUpdate
2梯浪、componentWillUpdate
3、render
4瓢娜、componentDidUpdate

但是不要直接修改 this.state挂洛,要通過 this.setState 方法來修改。

componentWillMount

該方法在首次渲染之前調(diào)用眠砾,也是再 render 方法調(diào)用之前修改 state 的最后一次機(jī)會虏劲。

render

該方法會創(chuàng)建一個虛擬DOM,用來表示組件的輸出褒颈。對于一個組件來講柒巫,render方法是唯一一個必需的方法。render方法需要滿足下面幾點:

  1. 只能通過 this.props 和 this.state 訪問數(shù)據(jù)(不能修改)

  2. 可以返回 null,false 或者任何React組件

  3. 只能出現(xiàn)一個頂級組件谷丸,不能返回一組元素

  4. 不能改變組件的狀態(tài)

  5. 不能修改DOM的輸出

render方法返回的結(jié)果并不是真正的DOM元素堡掏,而是一個虛擬的表現(xiàn),類似于一個DOM tree的結(jié)構(gòu)的對象刨疼。react之所以效率高泉唁,就是這個原因。

componentDidMount

該方法不會在服務(wù)端被渲染的過程中調(diào)用揩慕。該方法被調(diào)用時亭畜,已經(jīng)渲染出真實的 DOM,可以再該方法中通過 this.getDOMNode() 訪問到真實的 DOM(推薦使用 ReactDOM.findDOMNode())迎卤。

var data = [..];
var comp = React.createClass({
    render: function(){
        return <imput .. />
    },
    componentDidMount: function(){
        $(this.getDOMNode()).autoComplete({
            src: data
        })
    }
})

由于組件并不是真實的 DOM 節(jié)點拴鸵,而是存在于內(nèi)存之中的一種數(shù)據(jù)結(jié)構(gòu),叫做虛擬 DOM (virtual DOM)。只有當(dāng)它插入文檔以后劲藐,才會變成真實的 DOM 八堡。有時需要從組件獲取真實 DOM 的節(jié)點,這時就要用到 ref 屬性:

var Area = React.createClass({
    render: function(){
        this.getDOMNode(); //render調(diào)用時聘芜,組件未掛載秕重,這里將報錯

        return <canvas ref='mainCanvas'>
    },
    componentDidMount: function(){
        var canvas = this.refs.mainCanvas.getDOMNode();
        //這是有效的,可以訪問到 Canvas 節(jié)點
    }
})

需要注意的是厉膀,由于 this.refs.[refName] 屬性獲取的是真實 DOM 溶耘,所以必須等到虛擬 DOM 插入文檔以后,才能使用這個屬性服鹅,否則會報錯凳兵。

存在期

此時組件已經(jīng)渲染好并且用戶可以與它進(jìn)行交互,比如鼠標(biāo)點擊企软,手指點按庐扫,或者其它的一些事件,導(dǎo)致應(yīng)用狀態(tài)的改變仗哨,你將會看到下面的方法依次被調(diào)用

1形庭、componentWillReceiveProps
2、shouldComponentUpdate
3厌漂、componentWillUpdate
4萨醒、render
5、componentDidUpdate

componentWillReceiveProps

組件的 props 屬性可以通過父組件來更改苇倡,這時富纸,componentWillReceiveProps 將來被調(diào)用≈冀罚可以在這個方法里更新 state,以觸發(fā) render 方法重新渲染組件晓褪。

componentWillReceiveProps: function(nextProps){
    if(nextProps.checked !== undefined){
        this.setState({
            checked: nextProps.checked
        })
    }
}

shouldComponentUpdate

如果你確定組件的 props 或者 state 的改變不需要重新渲染,可以通過在這個方法里通過返回 false 來阻止組件的重新渲染综慎,返回 `false 則不會執(zhí)行 render 以及后面的 componentWillUpdate涣仿,componentDidUpdate 方法。

該方法是非必須的示惊,并且大多數(shù)情況下沒有在開發(fā)中使用好港。

shouldComponentUpdate: function(nextProps, nextState){
    return this.state.checked === nextState.checked;
    //return false 則不更新組件
}

componentWillUpdate

這個方法和 componentWillMount 類似,在組件接收到了新的 props 或者 state 即將進(jìn)行重新渲染前涝涤,componentWillUpdate(object nextProps, object nextState) 會被調(diào)用媚狰,注意不要在此方面里再去更新 props 或者 state。

componentDidUpdate

這個方法和 componentDidMount 類似阔拳,在組件重新被渲染之后,componentDidUpdate(object prevProps, object prevState) 會被調(diào)用『Γ可以在這里訪問并修改 DOM辨宠。

銷毀時

componentWillUnmount

每當(dāng)React使用完一個組件,這個組件必須從 DOM 中卸載后被銷毀货裹,此時 componentWillUnmout 會被執(zhí)行嗤形,完成所有的清理和銷毀工作,在 componentDidMount 中添加的任務(wù)都需要再該方法中撤銷弧圆,如創(chuàng)建的定時器或事件監(jiān)聽器赋兵。

當(dāng)再次裝載組件時,以下方法會被依次調(diào)用:

1搔预、getInitialState
2霹期、componentWillMount
3、render
4拯田、componentDidMount

反模式

在 getInitialState 方法中历造,嘗試通過 this.props 來創(chuàng)建 state 的做法是一種反模式。

//反模式
getDefaultProps: function(){
    return {
        data: new Date()
    }
},
getInitialState: function(){
    return {
        day: this.props.date - new Date()
    }
},
render: function(){
    return <div>Day:{this.state.day}</div>
}

經(jīng)過計算后的值不應(yīng)該賦給 state船庇,正確的模式應(yīng)該是在渲染時計算這些值吭产。這樣保證了計算后的值永遠(yuǎn)不會與派生出它的 props 值不同步。

//正確模式
getDefaultProps: function(){
    return {
        data: new Date()
    }
},
render: function(){
    var day = this.props.date - new Date();
    return <div>Day:{day}</div>
}

如果只是簡單的初始化 state鸭轮,那么應(yīng)用反模式是沒有問題的臣淤。

總結(jié)

以下面的一張圖總結(jié)組件的生命周期:

-https://image-static.segmentfault.com/315/625/3156257312-56761eb64bbfc

原文:http://www.ido321.com/1653.html

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市窃爷,隨后出現(xiàn)的幾起案子荒典,更是在濱河造成了極大的恐慌,老刑警劉巖吞鸭,帶你破解...
    沈念sama閱讀 219,490評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件寺董,死亡現(xiàn)場離奇詭異,居然都是意外死亡刻剥,警方通過查閱死者的電腦和手機(jī)遮咖,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來造虏,“玉大人御吞,你說我怎么就攤上這事±炫海” “怎么了陶珠?”我有些...
    開封第一講書人閱讀 165,830評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長享钞。 經(jīng)常有香客問我揍诽,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,957評論 1 295
  • 正文 為了忘掉前任暑脆,我火速辦了婚禮渠啤,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘添吗。我一直安慰自己沥曹,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,974評論 6 393
  • 文/花漫 我一把揭開白布碟联。 她就那樣靜靜地躺著妓美,像睡著了一般。 火紅的嫁衣襯著肌膚如雪鲤孵。 梳的紋絲不亂的頭發(fā)上壶栋,一...
    開封第一講書人閱讀 51,754評論 1 307
  • 那天,我揣著相機(jī)與錄音裤纹,去河邊找鬼委刘。 笑死,一個胖子當(dāng)著我的面吹牛鹰椒,可吹牛的內(nèi)容都是我干的锡移。 我是一名探鬼主播,決...
    沈念sama閱讀 40,464評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼漆际,長吁一口氣:“原來是場噩夢啊……” “哼淆珊!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起奸汇,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤施符,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后擂找,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體戳吝,經(jīng)...
    沈念sama閱讀 45,847評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,995評論 3 338
  • 正文 我和宋清朗相戀三年贯涎,在試婚紗的時候發(fā)現(xiàn)自己被綠了听哭。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,137評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡塘雳,死狀恐怖陆盘,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情败明,我是刑警寧澤隘马,帶...
    沈念sama閱讀 35,819評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站妻顶,受9級特大地震影響酸员,放射性物質(zhì)發(fā)生泄漏蜒车。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,482評論 3 331
  • 文/蒙蒙 一沸呐、第九天 我趴在偏房一處隱蔽的房頂上張望醇王。 院中可真熱鬧呢燥,春花似錦崭添、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至寞埠,卻和暖如春屁置,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背仁连。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評論 1 272
  • 我被黑心中介騙來泰國打工蓝角, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人饭冬。 一個月前我還...
    沈念sama閱讀 48,409評論 3 373
  • 正文 我出身青樓使鹅,卻偏偏與公主長得像,于是被迫代替她去往敵國和親昌抠。 傳聞我的和親對象是個殘疾皇子患朱,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,086評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 作為一個合格的開發(fā)者,不要只滿足于編寫了可以運行的代碼炊苫。而要了解代碼背后的工作原理裁厅;不要只滿足于自己的程序...
    六個周閱讀 8,449評論 1 33
  • 40、React 什么是React侨艾?React 是一個用于構(gòu)建用戶界面的框架(采用的是MVC模式):集中處理VIE...
    萌妹撒閱讀 1,017評論 0 1
  • react的生命周期(二) 前面已經(jīng)詳細(xì)講解過react的生命周期执虹,具體可以參考我的另一篇文章:https://w...
    龍波帝國閱讀 227評論 0 0
  • React基礎(chǔ) React組件化編程 Create React App 創(chuàng)建React 前端工程 題外話題:頁面性...
    BeautifulHao閱讀 1,543評論 0 3
  • 原教程內(nèi)容詳見精益 React 學(xué)習(xí)指南,這只是我在學(xué)習(xí)過程中的一些閱讀筆記唠梨,個人覺得該教程講解深入淺出袋励,比目前大...
    leonaxiong閱讀 2,840評論 1 18