1.react生命周期(舊版)
1.1react初始掛載時的生命周期
1:構造器-constructor
// 構造器constructor(props) {console.log('1:構造器-constructor');super(props)// 初始化狀態this.state = {count: 0}}
?2:組件將要掛載-componentWillMount
// 組件將要掛載componentWillMount() {console.log('2:組件將要掛載-componentWillMount');}
3:開始渲染-render
render(){console.log('3:開始渲染-render');const {count} = this.statereturn(<div><h2>當前的和為{count}</h2><button onClick={this.add}>點我+1</button><button onClick={this.death}>卸載DOM</button></div>)}
?4:組件掛載完成-componentDidMount
// 組件掛載完成componentDidMount() {console.log('4:組件掛載完成-componentDidMount');}
?5:組件卸載-componentWillUnmount
// 組件卸載componentWillUnmount() {console.log('5:組件卸載-componentWillUnmount');}
代碼實現演示
點擊卸載dom后?
?整體代碼
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Hello,React生命周期(舊)</title>
</head><body><!-- 容器 --><div id="test"></div><!-- {/* // 引入 React核心庫 */} --><script src="https://unpkg.com/react@16/umd/react.production.min.js"></script><!-- {/* // 引入 react-dom 用于支持 react 操作 DOM */} --><script src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script><!-- {/* // 引入 babel:1. ES6 ==> ES5 2. jsx ==> js */} --><script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script><!-- {/* // 引入 JSX 語法 */} --><script type="text/babel">// 1. 創建組件class Count extends React.Component {// 構造器constructor(props) {console.log('1:構造器-constructor');super(props)// 初始化狀態this.state = {count: 0}}add=()=>{// 獲取原狀態const {count} = this.state// 狀態更新this.setState({count: count+1})}death=()=>{ReactDOM.unmountComponentAtNode(document.getElementById('test'))}// 組件將要掛載componentWillMount() {console.log('2:組件將要掛載-componentWillMount');}// 組件掛載完成componentDidMount() {console.log('4:組件掛載完成-componentDidMount');}// 組件卸載componentWillUnmount() {console.log('5:組件卸載-componentWillUnmount');}render(){console.log('3:開始渲染-render');const {count} = this.statereturn(<div><h2>當前的和為{count}</h2><button onClick={this.add}>點我+1</button><button onClick={this.death}>卸載DOM</button></div>)}}ReactDOM.render(<Count />,document.getElementById('test'))</script>
</body></html>
?1.2.react更新數據setState
1:shouldComponentUpdate-判斷是否需要更新
// 控制組件更新 默認不寫此鉤子函數 返回true 組件更新shouldComponentUpdate(nextProps, nextState) { console.log('1:shouldComponentUpdate-判斷是否需要更新');return true}
2:componentWillUpdate-組件將要更新
// 組件將要更新componentWillUpdate(nextProps, nextState) {console.log('2:componentWillUpdate-組件將要更新');}
3:開始渲染-render
render(){console.log('3:開始渲染-render');const {count} = this.statereturn(<div><h2>當前的和為{count}</h2><button onClick={this.add}>點我+1</button><button onClick={this.death}>卸載DOM</button></div>)}
?4:componentDidUpdate-組件更新完成
// 組件更新完成componentDidUpdate(prevProps, prevState) {console.log('4:componentDidUpdate-組件更新完成');}
5:組件卸載-componentWillUnmount
// 組件卸載componentWillUnmount() {console.log('5:組件卸載-componentWillUnmount');}
整體代碼?
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Hello,React生命周期(舊)</title>
</head><body><!-- 容器 --><div id="test"></div><!-- {/* // 引入 React核心庫 */} --><script src="https://unpkg.com/react@16/umd/react.production.min.js"></script><!-- {/* // 引入 react-dom 用于支持 react 操作 DOM */} --><script src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script><!-- {/* // 引入 babel:1. ES6 ==> ES5 2. jsx ==> js */} --><script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script><!-- {/* // 引入 JSX 語法 */} --><script type="text/babel">// 1. 創建組件class Count extends React.Component {state = {count: 0}add=()=>{// 獲取原狀態const {count} = this.state// 狀態更新this.setState({count: count+1})}death=()=>{ReactDOM.unmountComponentAtNode(document.getElementById('test'))}// 組件卸載componentWillUnmount() {console.log('5:組件卸載-componentWillUnmount');}// 控制組件更新 默認不寫此鉤子函數 返回true 組件更新shouldComponentUpdate(nextProps, nextState) { console.log('1:shouldComponentUpdate-判斷是否需要更新');return true}// 組件將要更新componentWillUpdate(nextProps, nextState) {console.log('2:componentWillUpdate-組件將要更新');}// 組件更新完成componentDidUpdate(prevProps, prevState) {console.log('4:componentDidUpdate-組件更新完成');}render(){console.log('3:開始渲染-render');const {count} = this.statereturn(<div><h2>當前的和為{count}</h2><button onClick={this.add}>點我+1</button><button onClick={this.death}>卸載DOM</button></div>)}}ReactDOM.render(<Count />,document.getElementById('test'))</script>
</body></html>
1.3.forceUpdate聲明周期函數強制刷新
forceUpdate--》componentWillUpdate--》render--》componentDidUpdate--》componentWillUnmount
1.4父組件調用子組件render生命周期
componentWillReceiveProps--生命周期鉤子函數---父組件調用子組件 第二次渲染,其他的調用子組件的生命周期如setState以后執行生命周期一致。
父組件A
// 創建組件A--父組件class A extends React.Component {// 初始化狀態state={carName:'奧迪'}// 事件changeCarName=()=>{ this.setState({carName: '寶馬'})}render() {return (<div><div>A組件</div><button onClick={this.changeCarName}>修改車名</button>{/*將修改的車名傳遞給子組件--B*/}<B carName={this.state.carName} /></div>)}}
子組件B
// 創建組件B--子組件class B extends React.Component {// 生命周期鉤子函數---父組件調用子組件 第二次渲染componentWillReceiveProps() {console.log('b--componentWillReceiveProps');}render() {return (// B--props 接收父組件傳遞的props<div>B組件,接收父組件傳遞的props:{this.props.carName}</div>)}}
1.5 舊版生命周期總結?
????????
基礎開發中常用的生命周期鉤子:
- componentDidMount:初始化做的事情,開啟定時器,發送網絡請求,訂閱消息。
- render:渲染結構。
- componentWillUnmount:收尾,關閉定時器,取消消息。
2.react生命周期(17)
componentWillMount,componentWillReceiveProps,componentWillUpdate,在新的react17上中要加前綴UNSAFE。
2.1getDerivedStateFromProps靜態生命周期方法(使用頻率少)
????????允許組件在渲染前根據?props
?的變化更新其內部狀態。它在?render()
?方法之前被調用,主要用于處理那些狀態依賴于?props
?變化的罕見場景。
1.注意
無法訪問?this
(即組件實例)
2.調用時機:
組件首次掛載時(類似于?constructor
)
props
?更新時(父組件重新渲染或?props
?發生變化)
強制更新時(this.forceUpdate()
)
3.返回值:
必須返回一個對象來更新狀態,或返回?null
?表示不更新狀態
返回的新狀態對象會與現有狀態合并
4.使用場景:
罕見情況下,狀態需要依賴于?props
?的變化(例如,跟蹤先前的?props
?值)。
當?props
?變化時重置狀態(例如,父組件傳遞的?prop
?變化時清空表單輸入)。
5.代碼展示:
class Example extends React.Component {state = {derivedValue: 0,prevValue: 0, // 用于存儲先前的 prop 值};static getDerivedStateFromProps(nextProps, prevState) {// 僅在 props.value 變化時更新狀態if (nextProps.value !== prevState.prevValue) {return {derivedValue: nextProps.value * 2, // 根據 prop 推導狀態prevValue: nextProps.value, // 更新存儲的先前 prop 值};}return null; // 無變化時不更新狀態}render() {return <div>Derived Value: {this.state.derivedValue}</div>;}
}
2.2?getSnapshotBeforeUpdate
?(組件更新前捕獲當前信息-DOM狀態)
? ? ? ? 主要用于組件更新前捕獲當前信息,并將信息傳遞給componentDidUpdate,便于更新后進行對應的調整,
調用時機:在render后,DOM更新前:調用時機介于render與componentDidUpdate間。
接收參數:接收兩個參數,prevProps(更新前的props),prevState(更新前的state)。
使用場景:捕獲DOM狀態(列表更新,捕獲滾動位置,更新后恢復滾動位置)。
componentDidUpdate配合使用:getSnapShotBeforeUpdate返回值作為它的第三個參數(snapshot)傳遞。在其中根據snapshot的值進行對應的操作。
使用getSnapShotBeforeUpdate保持滾動位置不變:
import React from 'react';class ScrollingList extends React.Component {constructor(props) {super(props);this.listRef = React.createRef();this.state = {items: ['Item 1', 'Item 2', 'Item 3'],};}componentDidMount() {setInterval(() => {this.setState(prevState => ({items: [`New Item ${prevState.items.length + 1}`, ...prevState.items],}));}, 1000);}getSnapshotBeforeUpdate(prevProps, prevState) {// 捕獲更新前的滾動位置if (prevState.items.length < this.state.items.length) {const list = this.listRef.current;return list.scrollHeight - list.scrollTop;}return null;}componentDidUpdate(prevProps, prevState, snapshot) {// 根據快照調整滾動位置if (snapshot !== null) {const list = this.listRef.current;list.scrollTop = list.scrollHeight - snapshot;}}render() {return (<divref={this.listRef}style={{ height: '100px', overflow: 'auto', border: '1px solid black' }}>{this.state.items.map((item, index) => (<div key={index}>{item}</div>))}</div>);}
}export default ScrollingList;