class式元件的生命周期API
- 定義class元件
- class元件的生命周期-分為3大部分
-
- 挂載 -> (Mount):元件第一次在DOM樹中渲染
-
- 1.constructor(props)
- 2.render()
- 3.componentDidMount()
- 更新 -> (update):元件更新,重新渲染
-
-
-
- 1.static getDerivedStateFromProps(props, state) 不常用
- 2.shouldComponentUpdate(nextProps, nextState) 不常用
- 3.getSnapshotBeforeUpdate(prevProps, prevState)不常用
-
- 4.componentDidUpdate(prevProps,prevState,snapshot)
-
- 解除安裝 ->(Unmount):元件從DOM樹中删除
-
- 1.componentWillUnmount()
定義class元件
class Welcome extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
1.需繼承React.component
2.在 React.Component 的子類中有個必須定義的 render() 函數
class元件的生命周期-分為3大部分
下面常用的生命周期方法會被加粗。其餘生命周期函數的使用則相對罕見。
挂載 -> (Mount):元件第一次在DOM樹中渲染
當元件執行個體被建立并插入 DOM 中時,其生命周期調用順序如下:
- constructor(): 在 React 元件挂載之前,會調用它的構造函數
- static getDerivedStateFromProps()
- render():React渲染
- componentDidMount(): 在元件挂載後(插入 DOM 樹中)立即調用。
1.constructor(props)
我們把元件渲染,并且構造DOM元素插入到頁面的過程稱為元件的挂載
在 React 元件挂載之前,會調用它的構造函數。在為 React.Component 子類實作構造函數時,在其他語句之前前調用 super(props)。否則,this.props 在構造函數中可能會出現未定義的 bug。
通常,react中,構造函數僅用于一下兩種情況
1.給this.state 指派對象初始化内部state (初始化state值)
2.為事件處理函數綁定執行個體
如果不初始化state或不進行方法綁定,則不需要為React元件實作構造函數
注意:
- 在constructor()函數中不要調用setState()方法,可直接為this.state賦初始值state
- 也隻能在構造函數中直接為this.state指派,其他方法中指派應使用this.setState()
- 要避免在構造函數中引入任何副作用或訂閱。如遇到此場景,請将對應的操作放置在 componentDidMount 中。
constructor(props){
super(props);
//不要在這裡調用 this.setState()
this.state = {counter:0};
this.handleClick = this.handleClick.bind(this)
}
避免将 props 的值複制給 state!這是一個常見的錯誤:
constructor(props) {
super(props);
// 不要這樣做
this.state = { color: props.color };
}
如此做毫無必要(你可以直接使用 this.props.color),同時還産生了 bug (更新 prop 中的 color 時,并不會影響 state)。
隻有在你刻意忽略 prop 更新的情況下使用。此時,應将 prop 重命名為 initialColor 或 defaultColor。必要時,你可以修改它的 key,以強制“重置”其内部 state。
2.render()
render()方法是class元件中唯一必須實作的方法
1.初始化:React在應用初始化的時候,會渲染全部元件
2.setState()在任何情況下都會導緻元件的重新渲染,即使state未發生變化
當一個元件調用了setState()函數時,不論state是否發生了變化,該元件都将被重新渲染。
3.隻要父元件重新渲染了,那麼子元件就會重新渲染。即使元件未發生變化,并且從父元件接收的props也沒有發生變化,但是隻要父元件重新渲染了,那麼子元件就會重渲染。
當render被調用時,它會檢查this.props和this.state的變化并傳回一下類型之一
- React元素: JSX/自定義元件
- 數組或fragments:一個元件傳回多個元素
render() {
return (
<React.Fragment>
<ChildA />
<ChildB />
<ChildC />
</React.Fragment>
);
}
- Portals:将子節點渲染到存在于父元件以外的 DOM 節點的優秀的方案
- 字元串或數值類型:在DOM中被渲染為文本節點
- 布爾類型或 null:什麼都不渲染
render() 函數應該為純函數,這意味着在不修改元件 state 的情況下,每次調用時都傳回相同的結果,并且它不會直接與浏覽器互動。
如需與浏覽器進行互動,請在 componentDidMount() 或其他生命周期方法中執行你的操作
注意:
如果 shouldComponentUpdate() 傳回 false,則不會調用 render()。
React的元件重渲染機制,是一個嚴謹的做法,因為它避免了,狀态更新後,手動去重渲染相關元件的操作。但是有些時候我們更新了某個元件的資料,但是并不想讓與其相關的其他元件被重渲染,因為反複的重渲染未變化的元件,既耗時也會影響性能,此時就需要對React的重渲染進行優化
3.componentDidMount()
componentDidMount() 會在元件挂載後(插入 DOM 樹中)立即調用。
依賴于 DOM 節點的初始化應該放在這裡。
如需通過網絡請求擷取資料,此處是執行個體化請求的好地方。
這個方法是比較适合添加訂閱的地方。如果添加了訂閱,請不要忘記在 componentWillUnmount() 裡取消訂閱(釋出類似觸發事件,訂閱類似監聽事件)
可以在 componentDidMount() 裡直接調用 setState()。它将觸發額外渲染,但此渲染會發生在浏覽器更新螢幕之前。如此保證了即使在 render() 兩次調用的情況下,使用者也不會看到中間狀态。請謹慎使用該模式,因為它會導緻性能問題。通常,你應該在 constructor() 中初始化 state。如果你的渲染依賴于 DOM 節點的大小或位置,比如實作 modals 和 tooltips 等情況下,你可以使用此方式處理
更新 -> (update):元件更新,重新渲染
- static getDerivedStateFromProps() :不常用 擷取派生狀态
- shouldComponentUpdate():偶爾用 當傳回值為 false,則不會調用 componentDidUpdate()和render()。
- render()
- getSnapshotBeforeUpdate(): 不常用 擷取更新前快照
- componentDidUpdate():更新後會立即調用
元件更新相關函數,在元件初始挂載的時候都不會調用。
1.static getDerivedStateFromProps(props, state) 不常用
在調用 render 方法之前調用,并且在初始挂載及後續更新時都會被調用。它應傳回一個對象來更新 state,如果傳回 null 則不更新任何内容。
此方法無權通路元件執行個體
2.shouldComponentUpdate(nextProps, nextState) 不常用
在元件接收到新的props或state時調用,通過傳回值來确定是否重新渲染目前元件
預設行為是 state 每次發生變化元件都會重新渲染。
當 props 或 state 發生變化時,shouldComponentUpdate() 會在渲染render執行之前被調用。傳回值預設為 true。首次渲染或使用 forceUpdate() 時不會調用該方法。
此方法僅作為性能優化的方式而存在。不要企圖依靠此方法來“阻止”渲染,因為這可能會産生 bug。
一定要手動編寫此函數,可以将 this.props 與 nextProps 以及 this.state 與nextState 進行比較,并傳回 false 以告知 React 可以跳過更新。
請注意,傳回 false 并不會阻止子元件在 state 更改時重新渲染。
不建議在 shouldComponentUpdate() 中進行深層比較或使用
JSON.stringify()。這樣非常影響效率,且會損害性能。
目前,如果 shouldComponentUpdate() 傳回 false,則不會調用 UNSAFE_componentWillUpdate(),render() 和 componentDidUpdate()
3.getSnapshotBeforeUpdate(prevProps, prevState)不常用
最近一次渲染輸出(送出到 DOM 節點)之前調用。它使得元件能在發生更改之前從 DOM 中捕獲一些資訊(例如,滾動位置)。此生命周期方法的任何傳回值将作為參數傳遞給 componentDidUpdate()。
此用法并不常見,但它可能出現在 UI 進行中,如需要以特殊方式處理滾動位置的聊天線程等。
4.componentDidUpdate(prevProps,prevState,snapshot)
componentDidUpdate() 在更新後會立即調用,首次渲染不會執行該方法,元件更新,重渲染完畢後調用,prevProps 和prevState ,分别表示元件更新前的props和state
當元件更新後,可以在此處對 DOM 進行操作。如果你對更新前後的 props 進行了比較,也可以選擇在此處進行網絡請求。(例如,當 props 未發生變化時,則不會執行網絡請求)。
componentDidUpdate(prevProps){
//典型用法 (不要忘了比較props):
if(this.props.userID !== prevProps.userID){
this.fetchData(this.props.userID)
}
}
可以在 componentDidUpdate() 中直接調用 setState(),但請注意它必須被包裹在一個條件語句裡,正如上述的例子那樣進行處理,否則會導緻死循環。
它還會導緻額外的重新渲染,雖然使用者不可見,但會影響元件性能。
如果元件實作了 getSnapshotBeforeUpdate() 生命周期(不常用),則它的傳回值将作為 componentDidUpdate() 的第三個參數 “snapshot” 參數傳遞。否則此參數将為 undefined。
注意:
如果 shouldComponentUpdate() 傳回值為 false,則不會調用 componentDidUpdate()
解除安裝 ->(Unmount):元件從DOM樹中删除
當元件從 DOM 中移除時會調用如下方法:
componentWillUnmount():元件解除安裝及銷毀之前直接調用
1.componentWillUnmount()
componentWillUnmount() 會在元件解除安裝及銷毀之前直接調用。在此方法中執行必要的清理操作,例如,清除 timer,取消網絡請求或清除在 componentDidMount() 中建立的訂閱等
componentWillUnmount() 中不應調用 setState(),因為該元件将永遠不會重新渲染。元件執行個體解除安裝後,将永遠不會再挂載它。