摘要:一個組件的生命周期分為三個部分實(shí)例化存在期和銷毀時。如果回調(diào)函數(shù)以函數(shù)的方式來指定,那么在組件更新的時候回調(diào)會被調(diào)用次。
一個React組件的生命周期分為三個部分:實(shí)例化、存在期和銷毀時。
實(shí)例化階段
客戶端渲染時,如下依次被調(diào)用
getDefaultProps()
getInitialState()
componentWillMount()
render()
componentDidMount()
服務(wù)端渲染
getDefaultProps()
getInitialState()
componentWillMount()
render()
注意:componentDidMount()不會再服務(wù)端被渲染;
getDefaultProps
對于每個組件實(shí)例來講,這個方法只會調(diào)用一次,該組件類的所有后續(xù)應(yīng)用,getDefaultPops 將不會再被調(diào)用,其返回的對象可以用于設(shè)置默認(rèn)的props值。
var Hello = React.creatClass({ getDefaultProps: function(){ return { name: "pomy", git: "dwqs" } }, render: function(){ return (Hello,{this.props.name},git username is {this.props.dwqs}) } }); ReactDOM.render(, document.body);
也可以在掛載組件的時候設(shè)置 props。
var data = [{title: "Hello"}];
或者調(diào)用 setProps (一般不需要調(diào)用)來設(shè)置其 props
var data = [{title: "Hello"}]; var Hello = React.render(, document.body); Hello.setProps({data:data});
但只能在子組件或組件樹上調(diào)用 setProps。別調(diào)用 this.setProps 或者 直接修改 this.props。將其當(dāng)做只讀數(shù)據(jù)。
React通過 propTypes 提供了一種驗(yàn)證 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 ... }, //... })
或者
import React, { Component } from "react" import PropTypes from "prop-types" class BetterImage extends Component{...} BetterImage.PropTypes={ src: PropTypes.string, center: PropTypes.bool, loadingImage: PropTypes.string, defaultImage: PropTypes.string, onLoad: PropTypes.func, onError: PropTypes.func, onComplete: PropTypes.func } BetterImage.defaultProps={ .... }
getInitialState
對于組件的每個實(shí)例來說,這個方法的調(diào)用有且只有一次,用來初始化每個實(shí)例的 state,在這個方法里,可以訪問組件的 props。每一個React組件都有自己的 state,其與 props 的區(qū)別在于 state只存在組件的內(nèi)部,props 在所有實(shí)例中共享。
getInitialState 和 getDefaultPops 的調(diào)用是有區(qū)別的,getDefaultPops 是對于組件類來說只調(diào)用一次,后續(xù)該類的應(yīng)用都不會被調(diào)用,而 getInitialState 是對于每個組件實(shí)例來講都會調(diào)用,并且只調(diào)一次。
var LikeButton = React.createClass({ //初始化State getInitialState: function() { return {liked: false}; }, handleClick: function(event) { //設(shè)置修改State this.setState({liked: !this.state.liked}); }, render: function() { var text = this.state.liked ? "like" : "haven"t liked"; return (You {text} this. Click to toggle.
); } }); ReactDOM.render(, document.getElementById("example") );
每次修改 state,都會重新渲染組件,實(shí)例化后通過 state 更新組件,會依次調(diào)用下列方法:
1、shouldComponentUpdate 2、componentWillUpdate 3、render 4、componentDidUpdate
componentWillMount
在渲染前調(diào)用,在客戶端也在服務(wù)端。React 官方正式發(fā)布了 v16.3 版本。在這次的更新中,除了前段時間被熱烈討論的新 Context API 之外,新引入的兩個生命周期函數(shù) getDerivedStateFromProps,getSnapshotBeforeUpdate 以及在未來 v17.0 版本中即將被移除的三個生命周期函數(shù) componentWillMount,componentWillReceiveProps,componentWillUpdate .
在這個生命周期中你會遇到一下問題:
a.首屏無數(shù)據(jù)導(dǎo)致白屏
在 React 應(yīng)用中,許多開發(fā)者為了避免第一次渲染時頁面因?yàn)闆]有獲取到異步數(shù)據(jù)導(dǎo)致的白屏,而將數(shù)據(jù)請求部分的代碼放在了 componentWillMount 中,希望可以避免白屏并提早異步請求的發(fā)送時間。但事實(shí)上在 componentWillMount 執(zhí)行后,第一次渲染就已經(jīng)開始了,所以如果在 componentWillMount 執(zhí)行時還沒有獲取到異步數(shù)據(jù)的話,頁面首次渲染時也仍然會處于沒有異步數(shù)據(jù)的狀態(tài)。換句話說,組件在首次渲染時總是會處于沒有異步數(shù)據(jù)的狀態(tài),所以不論在哪里發(fā)送數(shù)據(jù)請求,都無法直接解決這一問題。而關(guān)于提早發(fā)送數(shù)據(jù)請求,官方也鼓勵將數(shù)據(jù)請求部分的代碼放在組件的 constructor 中,而不是 componentWillMount。
若是為了改善用戶體驗(yàn)曾經(jīng)用過的解決方法有兩個:
方法一:異步請求組件,使用nprogress 添加加載動畫;
import React, { Component } from "react" import NProgress from "nprogress" import "nprogress/nprogress.css" import "./customNprogress.styl" NProgress.configure({ showSpinner: false }) export default function asyncComponent(importComponent) { class AsyncComponent extends Component { state = { component: null } async componentDidMount() { NProgress.start() const { default: component } = await importComponent() NProgress.done() this.setState({ component }) } render() { const C = this.state.component return C ?: null } } return AsyncComponent } const AsyncNotFound = asyncComponent(() => import(/* webpackChunkName: "NotFound" */ "@/routes/NotFound"))
方法二:使用 onreadystatechange 去監(jiān)聽 readyState,在資源加載完成之前加載一個只有框架的靜態(tài)頁面,頁面不請求數(shù)據(jù)。當(dāng)數(shù)據(jù)請求完成之后再將路由切換到真實(shí)的首頁。
function listen () { if (document.readyState == "complete") { // 資源加載完成 ReactDom.render(, document.getElementById("root") ) } else { // 資源加載中 ReactDom.render( , document.getElementById("root") ) } } document.onreadystatechange = listen
具體參考解決React首屏加載白屏的問題
b.事件訂閱
另一個常見的用例是在 componentWillMount 中訂閱事件,并在 componentWillUnmount 中取消掉相應(yīng)的事件訂閱。但事實(shí)上 React 并不能夠保證在 componentWillMount 被調(diào)用后,同一組件的 componentWillUnmount 也一定會被調(diào)用。一個當(dāng)前版本的例子如服務(wù)端渲染時,componentWillUnmount 是不會在服務(wù)端被調(diào)用的,所以在 componentWillMount 中訂閱事件就會直接導(dǎo)致服務(wù)端的內(nèi)存泄漏。另一方面,在未來 React 開啟異步渲染模式后,在 componentWillMount 被調(diào)用之后,組件的渲染也很有可能會被其他的事務(wù)所打斷,導(dǎo)致 componentWillUnmount 不會被調(diào)用。而 **componentDidMount 就不存在這個問題,在 componentDidMount 被調(diào)用后,componentWillUnmount 一定會隨后被調(diào)用到,并根據(jù)具體代碼清除掉組件中存在的事件訂閱。**
render
該方法會創(chuàng)建一個虛擬DOM,用來表示組件的輸出。對于一個組件來講,render方法是唯一一個必需的方法。render方法需要滿足下面幾點(diǎn):
只能通過 this.props 和 this.state 訪問數(shù)據(jù)(不能修改)
可以返回 null,false(這種場景下,react渲染一個
只能出現(xiàn)一個頂級組件,不能返回一組元素
不能改變組件的狀態(tài)
不能修改DOM的輸出
render方法返回的結(jié)果并不是真正的DOM元素,而是一個虛擬的表現(xiàn),類似于一個DOM tree的結(jié)構(gòu)的對象。react之所以效率高,就是這個原因。
render執(zhí)行情況如下:
1. 首次加載 2. setState改變組件內(nèi)部state。 注意: 此處是說通過setState方法改變。 3. 接受到新的props
注意:因?yàn)閿?shù)據(jù)是異步的情況,會導(dǎo)致組件重復(fù)渲染
componentDidMount
該方法不會在服務(wù)端被渲染的過程中調(diào)用。該方法被調(diào)用時,已經(jīng)渲染出真實(shí)的 DOM,可以再該方法中通過 this.getDOMNode() 訪問到真實(shí)的 DOM(推薦使用 ReactDOM.findDOMNode())。
var data = [..]; var comp = React.createClass({ render: function(){ return}, componentDidMount: function(){ $(this.getDOMNode()).autoComplete({ src: data }) } })
由于組件并不是真實(shí)的 DOM 節(jié)點(diǎn),而是存在于內(nèi)存之中的一種數(shù)據(jù)結(jié)構(gòu),叫做虛擬 DOM (virtual DOM)。只有當(dāng)它插入文檔以后,才會變成真實(shí)的 DOM 。有時需要從組件獲取真實(shí) DOM 的節(jié)點(diǎn),這時就要用到 ref 屬性:
var Area = React.createClass({ render: function(){ this.getDOMNode(); //render調(diào)用時,組件未掛載,這里將報(bào)錯 return
需要注意的是,由于 this.refs.[refName] 屬性獲取的是真實(shí) DOM ,所以必須等到虛擬 DOM 插入文檔以后,才能使用這個屬性,否則會報(bào)錯。如果ref回調(diào)函數(shù)以inline函數(shù)的方式來指定,那么在組件更新的時候ref回調(diào)會被調(diào)用2次。第一次回調(diào)的時候傳入的參數(shù)是null,而第二次的時候才真正的傳入DOM節(jié)點(diǎn)
更多了解ref使用
從React官方文檔看 refs 的使用和未來
獲取真實(shí)dom,并獲取dom css 三種方法
此時組件已經(jīng)渲染好并且用戶可以與它進(jìn)行交互,比如鼠標(biāo)點(diǎn)擊,手指點(diǎn)按,或者其它的一些事件,導(dǎo)致應(yīng)用狀態(tài)的改變,你將會看到下面的方法依次被調(diào)用;
componentWillReceiveProps()
shouldComponentUpdate()
componentWillUpdate()
render()
componentDidUpdate()
componentWillReceiveProps
當(dāng)props發(fā)生變化時執(zhí)行,初始化render時不執(zhí)行,在這個回調(diào)函數(shù)里面,你可以根據(jù)屬性的變化,通過調(diào)用this.setState()來更新你的組件狀態(tài),舊的屬性還是可以通過this.props來獲取,這里調(diào)用更新狀態(tài)是安全的,并不會觸發(fā)額外的render調(diào)用。
componentWillReceiveProps: function(nextProps){ if(nextProps.checked !== undefined){ this.setState({ checked: nextProps.checked }) } }
了解更多點(diǎn)擊此處
shouldComponentUpdate
shouldComponentUpdate函數(shù)是重渲染時render()函數(shù)調(diào)用前被調(diào)用的函數(shù),它接受兩個參數(shù):nextProps和nextState,分別表示下一個props和下一個state的值。并且,當(dāng)函數(shù)返回false時候,阻止接下來的render()函數(shù)及后面的 componentWillUpdate,componentDidUpdate 方法的調(diào)用,阻止組件重渲染,而返回true時,組件照常重渲染。
了解更多點(diǎn)擊此處--真的講的好
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
constructor(props) // 初始化參數(shù) componentWillMount() render() // 第一次渲染 componentDidMount() **當(dāng)父組件向子組件傳入props發(fā)生改變后,依次調(diào)用** componentWillReceiveProps(nextProps) shouldComponentUpdate(nextProps, nextState) componentWillUpdate() render() //子組件更新渲染 componentDidUpdate() **當(dāng)組件自身state發(fā)生變化后** componentWillUpdate() render() //組件再次更新渲染 componentDidUpdate() 當(dāng)組件卸載 componentWillUnmount()
與低于React16版本的比較
React16新的生命周期棄用了componentWillMount、componentWillReceiveProps,componentWillUpdate
新增了getDerivedStateFromProps、getSnapshotBeforeUpdate來代替棄用的三個鉤子函數(shù)(componentWillMount、componentWillReceivePorps,componentWillUpdate)
React16并沒有刪除這三個鉤子函數(shù),但是不能和新增的鉤子函數(shù)(getDerivedStateFromProps、getSnapshotBeforeUpdate)混用,React17將會刪除componentWillMount、componentWillReceivePorps,componentWillUpdate
新增了對錯誤的處理(componentDidCatch)
相關(guān)文章那個生命周期方法更適合請求數(shù)據(jù)
react服務(wù)端渲染
來談?wù)凴eactv16.3新生命周期知識點(diǎn)及遇到的問題
React16版生命周期
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/103155.html
摘要:而生命周期鉤子,就是從生到死過程中的關(guān)鍵節(jié)點(diǎn)。異步渲染下的生命周期花了兩年時間祭出渲染機(jī)制。目前為這幾個生命周期鉤子提供了別名,分別是將只提供別名,徹底廢棄這三個大活寶。生命周期鉤子的最佳實(shí)踐是在這里初始化。 本文是『horseshoe·React專題』系列文章之一,后續(xù)會有更多專題推出來我的 GitHub repo 閱讀完整的專題文章來我的 個人博客 獲得無與倫比的閱讀體驗(yàn) 生命周期...
摘要:卸載階段組件卸載和銷毀老版生命周期之前的生命周期初始化階段涉及個鉤子函數(shù)這些方法會在組件初始化的時候被調(diào)用,只跟實(shí)例的創(chuàng)建有關(guān)。 前言:React 的版本從 v15 到 v16.3 ,再到v16.4,現(xiàn)在最新的版本是 v16.8了。其中最大的變化可能是React Hooks的加入,而最令人困惑的卻是它的生命周期,新舊生命周期函數(shù)混雜在一起,難免會讓許多新來者有很多困惑。所以這一篇我們來...
摘要:我們目前的計(jì)劃是為不安全生命周期引入別名,和。從現(xiàn)在開始,只有新的生命周期名稱將起作用。從版本開始,更新以響應(yīng)更改的推薦方法是使用新的靜態(tài)生命周期。 注釋:本文是根據(jù)React的官方博客翻譯而成(文章地址:https://reactjs.org/blog/2018...)。主要講述了React之后的更新方向,以及對之前生命周期所出現(xiàn)的問題的總結(jié),之后的React將逐步棄用一些生命周期和...
摘要:組件生命周期構(gòu)造方法是對類的默認(rèn)方法,通過命令生成對象實(shí)例時自動調(diào)用該方法。該生命周期可以發(fā)起異步請求,并。后廢棄該生命周期,可以在中完成設(shè)置渲染組件是一個組件必須定義的生命周期,用來渲染。該生命周期內(nèi)可以進(jìn)行。 React組件生命周期 constructor( ) 構(gòu)造方法 constructor是ES6對類的默認(rèn)方法,通過 new 命令生成對象實(shí)例時自動調(diào)用該方法。并且,該方法是...
摘要:所以對于組件更新階段的組件生命周期,我們簡單提及并且提供一些資料給大家。這里為了知識的完整,補(bǔ)充關(guān)于更新階段的組件生命周期你可以通過這個方法控制組件是否重新渲染。大家對這更新階段的生命周期比較感興趣的話可以查看官網(wǎng)文檔。 React.js 小書 Lesson20 - 更新階段的組件生命周期 本文作者:胡子大哈本文原文:http://huziketang.com/books/react...
摘要:組件生命周期此文章適合之前的版本,,添加了一些新的生命周期函數(shù),同時準(zhǔn)備廢棄一些會造成困擾的生命周期函數(shù)。每個生命周期階段調(diào)用的鉤子函數(shù)會略有不同。 React組件生命周期 此文章適合 React@17 之前的版本,React@16.3.0,添加了一些新的生命周期函數(shù),同時準(zhǔn)備廢棄一些會造成困擾的生命周期函數(shù)。所有如果在React@17 發(fā)布之前,這篇文章還是適用的。新的生命周期請看官...
閱讀 3547·2021-11-08 13:30
閱讀 3633·2019-08-30 15:55
閱讀 756·2019-08-29 15:16
閱讀 1797·2019-08-26 13:57
閱讀 2152·2019-08-26 12:18
閱讀 861·2019-08-26 11:36
閱讀 1800·2019-08-26 11:30
閱讀 3213·2019-08-23 16:46