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