相关文章
react 生命周期
一、挂载阶段 constructor() 组件的构造函数,在创建组件实例时调用。用于初始化状态和绑定事件处理函数。
类组件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 import React , { Component } from 'react' ;class MyComponent extends Component { constructor (props ) { super (props); this .state = { count : 0 }; this .handleClick = this .handleClick .bind (this ); } handleClick ( ) { this .setState ((prevState ) => ({ count : prevState.count + 1 })); } render ( ) { return ( <div > <p > Count: {this.state.count}</p > {/* 绑定事件处理函数 */} <button onClick ={this.handleClick} > Increment</button > </div > ); } }export default MyComponent ;
函数组件模拟
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 import React , { useState, useEffect } from 'react' ;function MyComponent ( ) { const [count, setCount] = useState (0 ); const handleClick = ( ) => { setCount (prevCount => prevCount + 1 ); }; return ( <div > <p > Count: {count}</p > {/* 绑定事件处理函数 */} <button onClick ={handleClick} > Increment</button > </div > ); }export default MyComponent ;
在这个示例中,我们使用 useState 来初始化状态 count。
static getDerivedStateFromProps(props, state): 在组件挂载之前调用,用于根据 props 来更新 state。它返回一个对象来更新 state,或者返回 null 表示不需要更新 state。
类组件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 import React , { Component } from 'react';class MyComponent extends Component { state = { value: '' }; static getDerivedStateFromProps(nextProps, prevState) { if (nextProps.value !== prevState.value) { return { value: nextProps.value }; } return null ; } render() { return ( <div> <p>Value : {this .state.value}</p> </div> ); } }class App extends Component { state = { inputValue: '' }; handleChange = (e) => { this .setState({ inputValue: e.target.value }); }; render() { return ( <div> <input type ="text" value={this .state.inputValue} onChange={this .handleChange} /> {} <MyComponent value={this .state.inputValue} /> </div> ); } }export default App ;
在这个示例中,MyComponent 组件接收一个名为 value 的 prop,当 value 发生变化时,我们希望组件的内部状态也跟着更新。通过 getDerivedStateFromProps 方法,我们可以在组件每次渲染之前检查 value 是否发生变化,如果发生变化则更新组件的 state。
函数组件模拟
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 import React , { useState, useEffect } from 'react' ;function MyComponent ({ value } ) { const [state, setState] = useState ('' ); useEffect (() => { setState (value); }, [value]); return ( <div > <p > Value: {state}</p > </div > ); }function App ( ) { const [inputValue, setInputValue] = useState ('' ); const handleChange = (e ) => { setInputValue (e.target .value ); }; return ( <div > <input type ="text" value ={inputValue} onChange ={handleChange} /> {/* 将输入框的值作为 props 传递给 MyComponent */} <MyComponent value ={inputValue} /> </div > ); }export default App ;
这个示例中,我们使用 useState 来创建状态,并在 useEffect 中监听 value 的变化,从而更新组件的内部状态。这样,就模拟了 getDerivedStateFromProps 的功能。
render() 渲染方法,用于生成组件的 JSX 结构。
类组件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 import React , { Component } from 'react' ;class Counter extends Component { constructor (props ) { super (props); this .state = { count : 0 }; } increment = () => { this .setState ((prevState ) => ({ count : prevState.count + 1 })); }; render ( ) { return ( <div > <p > Count: {this.state.count}</p > <button onClick ={this.increment} > Increment</button > </div > ); } }export default Counter ;
函数组件模拟
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import React , { useState } from 'react' ;function Counter ( ) { const [count, setCount] = useState (0 ); const increment = ( ) => { setCount (count + 1 ); }; return ( <div > <p > Count: {count}</p > <button onClick ={increment} > Increment</button > </div > ); }export default Counter ;
在函数式组件中,render 方法被替代为组件本身的返回值。
componentDidMount() 在组件挂载之后调用,可以进行 DOM 操作、数据获取等副作用操作。
类组件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import React , { Component } from 'react' ;class MyComponent extends Component { componentDidMount ( ) { console .log ('Component mounted' ); } render ( ) { return ( <div > <p > My Component</p > </div > ); } }export default MyComponent ;
函数组件模拟
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import React , { useEffect } from 'react' ;function MyComponent ( ) { useEffect (() => { console .log ('Component mounted' ); }, []); return ( <div > <p > My Component</p > </div > ); }export default MyComponent ;
在这个示例中,我们使用 useEffect 钩子函数来模拟 componentDidMount 方法的功能。传入空数组作为第二个参数,表示 useEffect 仅在组件挂载时执行一次。
二、更新阶段 static getDerivedStateFromProps(props, state) (同上)在更新阶段调用,用于根据 props 更新 state。
shouldComponentUpdate(nextProps, nextState) 在组件接收到新的 props 或 state 时调用,用于判断是否需要重新渲染组件。默认返回 true,表示组件总是会重新渲染。可以通过手动比较 props 和 state 来优化性能。
类组件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 import React , { Component } from 'react';class MyComponent extends Component { shouldComponentUpdate(nextProps, nextState) { if (nextProps.someProp !== this .props.someProp || nextState.someState !== this .state.someState) { return true ; } return false ; } render() { return ( <div> <p>{this .props.someProp}</p> </div> ); } }export default MyComponent ;
函数组件模拟
1 2 3 4 5 6 7 8 9 10 11 import React from 'react' ;function MyComponent ({ someProp } ) { return ( <div > <p > {someProp}</p > </div > ); }export default React .memo (MyComponent );
在这个示例中,我们使用 React.memo 高阶组件来包装函数式组件 MyComponent,以达到控制组件是否重新渲染的目的。React.memo 会对组件的 props 进行浅比较,如果 props 没有变化,则不重新渲染组件。
render() (同上)渲染方法,用于生成组件的 JSX 结构。
getSnapshotBeforeUpdate(prevProps, prevState) 在最近一次渲染输出(提交到 DOM 上)之前调用,用于获取更新前的 DOM 状态。它的返回值将作为第三个参数传递给 componentDidUpdate 方法。
类组件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 import React , { Component } from 'react' ;class MyComponent extends Component { constructor (props ) { super (props); this .state = { isVisible : true }; this .buttonRef = React .createRef (); } componentDidMount ( ) { setTimeout (() => { this .setState (prevState => ({ isVisible : !prevState.isVisible })); }, 1000 ); } getSnapshotBeforeUpdate (prevProps, prevState ) { return prevState.isVisible ; } componentDidUpdate (prevProps, prevState, snapshot ) { if (this .state .isVisible !== snapshot) { console .log ('Button visibility changed!' ); } } render ( ) { return ( <div > {this.state.isVisible && ( <button ref ={this.buttonRef} > Click me</button > )} </div > ); } }export default MyComponent ;
在这个示例中,MyComponent 组件每秒钟切换一次按钮的显示状态,getSnapshotBeforeUpdate 方法用于获取更新前的按钮可见状态,然后在 componentDidUpdate 方法中根据快照值判断按钮可见状态是否发生变化,并在控制台打印相应的信息。
函数组件模拟
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 import React , { useState, useEffect, useRef } from 'react' ;function MyComponent ( ) { const [isVisible, setIsVisible] = useState (true ); const buttonRef = useRef (null ); const prevIsVisibleRef = useRef (null ); useEffect (() => { const intervalId = setInterval (() => { setIsVisible (prev => !prev); }, 1000 ); return () => clearInterval (intervalId); }, []); useEffect (() => { prevIsVisibleRef.current = isVisible; }, [isVisible]); useEffect (() => { const prevIsVisible = prevIsVisibleRef.current ; if (prevIsVisible !== null && isVisible !== prevIsVisible) { console .log ('Button visibility changed!' ); } }); return ( <div > {isVisible && ( <button ref ={buttonRef} > Click me</button > )} </div > ); }export default MyComponent ;
在这个函数式组件中,我们使用了 useState 来管理按钮的可见状态,使用 useRef 来保存上一个可见状态的值,以便在更新后比较前后状态的变化。然后,我们使用两个 useEffect 钩子函数,一个用于模拟每秒钟切换按钮的显示状态,另一个用于获取更新前的状态并判断是否发生变化。
componentDidUpdate(prevProps, prevState, snapshot) 在组件更新(重新渲染)之后调用,可以进行 DOM 操作、数据更新等副作用操作。
类组件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 import React , { Component } from 'react' ;class MyComponent extends Component { constructor (props ) { super (props); this .state = { count : 0 }; } componentDidUpdate (prevProps, prevState ) { if (prevProps.userId !== this .props .userId ) { this .setState ({ count : 0 }); } } render ( ) { return ( <div > <p > User ID: {this.props.userId}</p > <p > Count: {this.state.count}</p > <button onClick ={() => this.setState(prevState => ({ count: prevState.count + 1 }))}> Increment </button > </div > ); } }export default MyComponent ;
在这个示例中,MyComponent 组件每秒钟切换一次按钮的显示状态,getSnapshotBeforeUpdate 方法用于获取更新前的按钮可见状态,然后在 componentDidUpdate 方法中根据快照值判断按钮可见状态是否发生变化,并在控制台打印相应的信息。
函数组件模拟
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 import React , { useState, useEffect } from 'react' ;function MyComponent ({ userId } ) { const [count, setCount] = useState (0 ); useEffect (() => { console .log ('Component updated!' ); setCount (0 ); }, [userId]); return ( <div > <p > User ID: {userId}</p > <p > Count: {count}</p > <button onClick ={() => setCount(prevCount => prevCount + 1)}> Increment </button > </div > ); }export default MyComponent ;
在这个示例中,我们使用 useEffect 钩子函数来模拟 componentDidUpdate。
三、卸载阶段 componentWillUnmount() 在组件卸载(销毁)之前调用,用于清理定时器、取消订阅等资源释放操作。
类组件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 import React , { Component } from 'react' ;class Timer extends Component { constructor (props ) { super (props); this .state = { seconds : 0 }; } componentDidMount ( ) { this .intervalId = setInterval (() => { this .setState (prevState => ({ seconds : prevState.seconds + 1 })); }, 1000 ); } componentWillUnmount ( ) { clearInterval (this .intervalId ); } render ( ) { return ( <div > <p > Timer: {this.state.seconds} seconds</p > </div > ); } }export default Timer ;
在这个示例中,MyComponent 组件每秒钟切换一次按钮的显示状态,getSnapshotBeforeUpdate 方法用于获取更新前的按钮可见状态,然后在 componentDidUpdate 方法中根据快照值判断按钮可见状态是否发生变化,并在控制台打印相应的信息。
函数组件模拟
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 import React , { useState, useEffect } from 'react' ;function Timer ( ) { const [seconds, setSeconds] = useState (0 ); useEffect (() => { const intervalId = setInterval (() => { setSeconds (prevSeconds => prevSeconds + 1 ); }, 1000 ); return () => { clearInterval (intervalId); }; }, []); return ( <div > <p > Timer: {seconds} seconds</p > </div > ); }export default Timer ;
在这个示例中,我们使用 useEffect 钩子函数来模拟 componentWillUnmount 的功能。在 useEffect 的回调函数中,我们启动了一个定时器,并返回了一个清理函数,在组件即将卸载时清除定时器。这样可以确保在组件从 DOM 中移除之前清除所有的副作用,从而保持组件的健壮性和可预测性。