React
組件的生命週期實際是提供給React
用於將React
元素構建渲染掛載到真實的Dom
節點的各個時期的鉤子函數。各個生命週期函數提供,使得在開發組件時能夠控制各個時期執行不一樣的操做,如異步的獲取數據等。 javascript
上圖是基於
React: '^16.4'
的生命週期java
組件首次被實例化建立並插入DOM
中須要執行的生命週期函數:react
state
或進行方法綁定時,須要定義constructor()
函數。不可在constructor()
函數中調用setState()
。getDerivedStateFromProps
函數返回咱們要的更新的state
,React
會根據函數的返回值拿到新的屬性。render()
函數,是類組件中惟一必須實現的方法。render()
函數應爲純函數,也就是說只要組件state
和props
沒有變化,返回的結果是相同的。其返回結果能夠是:一、React
元素;二、數組或 fragments;三、Portals;四、字符串或數值類型;五、布爾值或null。不可在render()
函數中調用setState()
。Dom
中調用此方法,能夠在此方法內執行反作用操做,如獲取數據,更新state
等操做。當組件的props
或state
改變時會觸發更新須要執行的生命週期函數:數組
getDerivedStateFromProps
會在調用 render
方法以前調用,而且在初始掛載及後續更新時都會被調用。它應返回一個對象來更新state
,若是返回null
則不更新任何內容。shouldComponentUpdate()
的返回值,判斷React
組件的是否執行更新操做。React.PureComponent
就是基於淺比較進行性能優化的。通常在實際組件實踐中,不建議使用該方法阻斷更新過程,若是有須要建議使用React.PureComponent
。shouldComponentUpdate()
返回false
值時,將不執行render()
函數。pre-commit
階段,此時已經能夠拿到Dom
節點數據了,該聲明週期返回的數據將做爲componentDidUpdate()
第三個參數進行使用。shouldComponentUpdate()
返回值false
時,則不會調用componentDidUpdate()
。componentWillUnmount()
會在組件卸載及銷燬以前直接調用。通常使用此方法用於執行反作用的清理操做,如取消定時器,取消事件綁定等。性能優化
import React from 'react';
export default class CancelDocumentEffect extends React.Component {
handleDocumentClick = (e) => {
console.log(`document has clicked: ${e}`);
}
componentDidMount() {
document.addEventLister('click', this.handleDocumentClick, false);
}
componentWillUnmount() {
document.removeEventLister('click', this.handleDocumentClick, false);
}
render() {
return (<p>this is test!</p>)
}
}
複製代碼
當渲染過程,生命週期,或子組件的構造函數中拋出錯誤會執行static getDerivedStateFromError()
或componentDidCatch()
生命週期函數。且基於此,React: '^16.0.0'
提出了錯誤邊界的概念。錯誤邊界實際上是一種可以捕獲它的子組件樹所產生的錯誤的React
組件,主要目標是在部分UI
的JavaScript
錯誤不會致使整個應用崩潰,而能夠進行錯誤處理,並進行優雅降級,渲染備用的UI
。可是錯誤邊界有必定的侷限性。 錯誤邊界沒法捕獲如下場景中產生的錯誤:異步
setTimeout
或requestAnimationFrame
回調函數)static getDerivedStateFromError(error)
:在渲染階段調用,不容許執行反作用,所以用戶渲染降級備用的UI
componentDidCatch(error, errorInfo)
:在提交階段調用,能夠執行反作用。 所以可用於記錄錯誤之類的狀況import React from 'react';
export default class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = {
hasError: false
};
}
static getDerivedStateFromError(error) {
this.setState({hasError: true});
}
componentDidCatch(error, errorInfo) {
logService(error, errorInfo);
}
render() {
const {hasError} = this.state;
const backupUI = <div>發生錯誤</div>
return hasError ? backupUI : this.props.children;
}
}
複製代碼