react生命週期的全面了解(附程式碼)
這篇文章帶給大家的內容是關於react生命週期的全面了解(附程式碼),有一定的參考價值,有需要的朋友可以參考一下,希望對你有幫助。
一個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 ( <p>Hello,{this.props.name},git username is {this.props.dwqs}</p> ) } }); ReactDOM.render(<Hello />, document.body);
也可以在掛載元件的時候設定 props。
var data = [{title: 'Hello'}]; <Hello data={data} />
或呼叫 setProps (一般不需要呼叫)來設定其 props
var data = [{title: 'Hello'}]; var Hello = React.render(<Demo />, 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 ( <p onClick={this.handleClick}> You {text} this. Click to toggle. </p> ); } }); ReactDOM.render( <LikeButton />, 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 ? <C {...this.props} /> : null } } return AsyncComponent } const AsyncNotFound = asyncComponent(() => import(/* webpackChunkName: "NotFound" */ '@/routes/NotFound'))
方法二:使用 onreadystatechange 去監聽readyState,在資源載入完成之前載入一個只有框架的靜態頁面,頁面不請求資料。當資料請求完成之後再將路由切換到真實的首頁。
function listen () { if (document.readyState == 'complete') { // 资源加载完成 ReactDom.render( <Provider store={store}> <Router> <Route path="/" component={Index}/> </Router> </Provider>, document.getElementById('root') ) } else { // 资源加载中 ReactDom.render( <Provider store={store}> <Router> <Route path="/" component={FirstScreen}/> </Router> </Provider>, 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 <imput .. /> }, componentDidMount: function(){ $(this.getDOMNode()).autoComplete({ src: data }) } })
由于组件并不是真实的 DOM 节点,而是存在于内存之中的一种数据结构,叫做虚拟 DOM (virtual DOM)。只有当它插入文档以后,才会变成真实的 DOM 。有时需要从组件获取真实 DOM 的节点,这时就要用到 ref 属性:
var Area = React.createClass({ render: function(){ this.getDOMNode(); //render调用时,组件未挂载,这里将报错 return <canvas ref='mainCanvas'> }, componentDidMount: function(){ var canvas = this.refs.mainCanvas.getDOMNode(); //这是有效的,可以访问到 Canvas 节点 } })
需要注意的是,由于 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
React v.16生命周期
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來取代棄用的三個鉤子函式(YponentWillUp、componentsWillive、component)誰#dponentWillUp、componentWillt、component)> React16並沒有刪除這三個鉤子函數,但是不能和新增的鉤子函數(getDerivedStateFromProps、getSnapshotBeforeUpdate)混用,React17將會刪除componentWillMount、componentWillReceivePorps,componentWillUpdate
- ##11錯誤的處理(componentDidCatch)
react影片教學
##以上是react生命週期的全面了解(附程式碼)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

如何使用WebSocket和JavaScript實現線上語音辨識系統引言:隨著科技的不斷發展,語音辨識技術已成為了人工智慧領域的重要組成部分。而基於WebSocket和JavaScript實現的線上語音辨識系統,具備了低延遲、即時性和跨平台的特點,成為了廣泛應用的解決方案。本文將介紹如何使用WebSocket和JavaScript來實現線上語音辨識系

WebSocket與JavaScript:實現即時監控系統的關鍵技術引言:隨著互聯網技術的快速發展,即時監控系統在各個領域中得到了廣泛的應用。而實現即時監控的關鍵技術之一就是WebSocket與JavaScript的結合使用。本文將介紹WebSocket與JavaScript在即時監控系統中的應用,並給出程式碼範例,詳細解釋其實作原理。一、WebSocket技

如何利用JavaScript和WebSocket實現即時線上點餐系統介紹:隨著網路的普及和技術的進步,越來越多的餐廳開始提供線上點餐服務。為了實現即時線上點餐系統,我們可以利用JavaScript和WebSocket技術。 WebSocket是一種基於TCP協定的全雙工通訊協議,可實現客戶端與伺服器的即時雙向通訊。在即時線上點餐系統中,當使用者選擇菜餚並下訂單

如何使用WebSocket和JavaScript實現線上預約系統在當今數位化的時代,越來越多的業務和服務都需要提供線上預約功能。而實現一個高效、即時的線上預約系統是至關重要的。本文將介紹如何使用WebSocket和JavaScript來實作一個線上預約系統,並提供具體的程式碼範例。一、什麼是WebSocketWebSocket是一種在單一TCP連線上進行全雙工

JavaScript和WebSocket:打造高效的即時天氣預報系統引言:如今,天氣預報的準確性對於日常生活以及決策制定具有重要意義。隨著技術的發展,我們可以透過即時獲取天氣數據來提供更準確可靠的天氣預報。在本文中,我們將學習如何使用JavaScript和WebSocket技術,來建立一個高效的即時天氣預報系統。本文將透過具體的程式碼範例來展示實現的過程。 We

JavaScript教學:如何取得HTTP狀態碼,需要具體程式碼範例前言:在Web開發中,經常會涉及到與伺服器進行資料互動的場景。在與伺服器進行通訊時,我們經常需要取得傳回的HTTP狀態碼來判斷操作是否成功,並根據不同的狀態碼來進行對應的處理。本篇文章將教你如何使用JavaScript來取得HTTP狀態碼,並提供一些實用的程式碼範例。使用XMLHttpRequest

用法:在JavaScript中,insertBefore()方法用於在DOM樹中插入一個新的節點。這個方法需要兩個參數:要插入的新節點和參考節點(即新節點將要插入的位置的節點)。

JavaScript是一種廣泛應用於Web開發的程式語言,而WebSocket則是一種用於即時通訊的網路協定。結合二者的強大功能,我們可以打造一個高效率的即時影像處理系統。本文將介紹如何利用JavaScript和WebSocket來實作這個系統,並提供具體的程式碼範例。首先,我們需要明確指出即時影像處理系統的需求和目標。假設我們有一個攝影機設備,可以擷取即時的影像數
