1、组件的生命周期概述.
生命周期
含义:
从组件出生到更新、改变、销毁(创建\更新\销毁)的整个阶段。
生命周期的钩子函数
含义:
组件的每个阶段都伴随着一些方法,就是生命周期的钩子函数,我们就是通过控制这些生命周期函数从而控制组件。
生命周期
意义:
组件的生命周期有助于理解组件的运行方式、完成更复杂的组件功能、分析组件错误原因
TIPS
只有类组件才有生命周期
2、 组件生命周期的三个阶段
1.每个阶段的执行时机 2、每个阶段钩子函数的执行顺序 3、每个阶段钩子函数的作用
组件的生命周期主要分为三个主要阶段:
挂载(Mounting)、
更新(Updating)、
卸载(Unmounting)
(1) 创建时
(2) 更新时
更新的三种情况:
1、setState 2、 forceUpdate 3、组件接受到新的props
示例代码:
组件的函数周期
render 生命周期渲染 componenetDidUpdate() 生命周期更新
注意部分:
seState 应该放在判断if 里面 ajax的请求部分应该放在这里
(3)组件卸载时(卸载阶段)
执行时间:组件从页面之中消失时
- componentDidMount(){}组件的挂载阶段
- componentWillUnmount(){}组件的卸载阶段
组件的挂载阶段执行的一些方法可以在组件的卸载阶段除去
3、旧版本-生命周期钩子函数(react 15 可直接跳过)
我们可以来看看React15 的生命周期函数
(1)
constructor()
: ES6 类中的构造函数,初始化使用(比如初始化组件状态(state)绑定事件处理器;),组件实例化时调用
(2)
componentWillReceiveProps()
: 一般使用都是传值componentWillReceiveProps(nextProps)
- 已废弃:这个生命周期函数就是在组件即将接收新的属性时被调用(旧版本React中就是更新用)。可以在这里比较新旧属性,然后更新组件的状态;
(3)
shouldComponentUpdate(nextProps, nextState)
: 组件接收到新的属性或者状态时,在更新组件之前调用shouldComponentUpdate()
函数。根据新的属性和状态判断是否需要重新渲染组件(性能优化常用)
(4)
componentWillMount()
:
- 已废弃:新版本不再推荐使用。 在组件即将被挂载到 DOM 中时被调用,很多时候我们可以使用
constructor()
或者componentDidMount()
来替代。
(5)
componentWillUpdate(nextProps, nextState)
: 已废弃:新版本不再推荐,在组件即将被更新之前被调用,我们可以在组件即将更新之前控制组件。
(6)
componentDidUpdate()
: 组件第一次被渲染到 DOM 中之后被调用。我们可以进行一些初始化的操作,获取远程数据、订阅事件等
(7)
render()
:render()
最重要
的生命周期函数之一,返回虚拟 DOM 元素,渲染组件外观和结构.
(8)
componentWillUnmount()
: 在组件即将被销毁和从 DOM 中移除之前被调用,就类似砸门在vue销毁之前一样,可以取消订阅、清除定时器。
4、重要
- 新版本-生命周期钩子函数(react 16 )
(1) constructor
在类组件创建实例时调用,初始化的时候执行一次,可以在组件进行初始化时候控制组件。
不定义 constructor
,React 会自动为组件创建一个默认的 constructor
我们来写一个简单的类组件
看看
js
复制代码
import React from 'react'; // 生命周期 class Demo extends React.Component { constructor(props: any) { super(props); //super作用 : 传递props,才能在接下来的上下文中,获取到props console.log('constructor-生命周期'); } render() { return ( <div className="App" id='link'>constructor</div> ); } } export default Demo;
作用
js
复制代码
- 初始化 state ,获取路由中的参数,组件传值赋值给 state等 。 - 绑定类组件事件,绑定 this 、节流,防抖。 - 对类组件进行生命周期的劫持,渲染劫持等。
js
复制代码
import React from 'react'; // 01 初始化状态 class Demo extends React.Component { constructor(props: any) { super(props); console.log(props,'props'); console.log('constructor-生命周期'); //初始化状态 this.state={ name:'alien', count: 0, } } export default Demo; // 02 **绑定事件处理器** class MyComponent extends React.Component { constructor(props) { super(props); this.handleClick = this.handleClick.bind(this); } handleClick(name: string) { console.log(name,'name'); return () => { console.log('handleClick'); } } } 03 **初始化引用** constructor(props) { super(props); this.myRef = React.createRef(); }
(2) getDerivedStateFromProps (react 16 新增)
js
复制代码
getDerivedStateFromProps(nextProps,prevState) // nextProps 父组件新传递的 props ; // prevState 组件在此次更新前的 state
组件更新执行包括(props变化,setState、forceUpdate)
注意点
getDerivedStateFromProps 被定义为 static 方法 —— static 方法内部拿不到组件实例的 this
任何操作 this.fetch()之类的都不可以在里卖面使用
在组件的操作之中大致归为两类
- 基于 props 更新状态
js
复制代码
class MyComponent extends React.Component { constructor(props) { super(props); this.state = { value: '' }; } static getDerivedStateFromProps(nextProps, prevState) { // 如果接收到新的值,更新状态 if (nextProps.value !== prevState.value) { return { value: nextProps.value }; } return null; // 不更新状态 } // ... }
- 控制内部状态
js
复制代码
class MyComponent extends React.Component { constructor(props) { super(props); this.state = { isFocused: false }; } static getDerivedStateFromProps(nextProps, prevState) { if (nextProps.autoFocus && !prevState.isFocused) { return { isFocused: true }; } return null; } // ... }
(3 )render
渲染时操作元素
(4)componentDidMount
js
复制代码
componentDidMount(){} 组件挂载到 DOM 后立即被调用,跟上面作用一样,进行数据获取、订阅事件等初始化工作
(5)shouldComponentUpdate
就是判断是否需要重新渲染组件,主要依赖传入的props 或 state 来决定是否更新组件
js
复制代码
shouldComponentUpdate(newProps,newState,nextContext){} // 参数含义 (新的 旧的 更新的)
(6)getSnapshotBeforeUpdate
组件更新 DOM 之前被调用(如滚动位置的使用)
js
复制代码
getSnapshotBeforeUpdate(prevProps, prevState) { // 返回滚动位置 return this.myRef.current.scrollHeight; // prevProps更新前的props preState更新前的state; } // 参数含义 (新的 旧的 更新的)
注意点:
getSnapshotBeforeUpdate
必须与componentDidUpdate
一起使用,因为它的返回值会作为第三个参数传递给componentDidUpdate
。- 我们在大多数情况下不使用,它主要用于处理一些处理复杂的 UI 动画或需要手动保存和恢复某些 DOM 状态的情况。
(7)componentDidUpdate
组件更新(re-render)完成之后被调用
js
复制代码
componentDidUpdate(prevProps, prevState, snapshot){} // 更新之前的 props 更新之前的 prevState 更新之前的 DOM 信息 // 操作可能会触发额外的组件更新,因此需要谨慎处理,以避免陷入无限循环
(8) componentWillUnmount
组件销毁阶段唯一执行的生命周期
componentDidMount 设置定时器,componentWillUnmount清楚定时器
js
复制代码
import React from 'react'; // 生命周期 class Demo extends React.Component { constructor(props) { super(props); console.log(props,'props'); console.log('constructor-生命周期'); //初始化状态 this.state={ count: 0, } } componentDidMount(){ console.log('componentDidMount'); this.interval = setInterval(() => { this.setState({ count: this.state.count + 1 }); }, 1000); } componentWillUnmount() { console.log('componentWillUnmount'); clearInterval(this.interval); } render() { return ( <> <p>Timer: {this.state.count}</p> </> ); } } export default Demo;
刷新以后组件重新销毁创建定时器
6、(函数式组件)React声明周期函数
需要注意的是:
React函数式组件中,没有像类组件那样明确的声明周期函数,可以通过 React Hooks实现类似的生命周期函数
常用的 React Hooks 及其对应的生命周期函数
js
复制代码
1. `useState`: 用于声明状态变量,类似于类组件中的 `state` 1. `useEffect`: 在组件渲染后执行副作用操作,类似于类组件中的 `componentDidMount`, `componentDidUpdate`, `componentWillUnmount` 1. `useContext`: 用于访问 React 的上下文,类似于类组件中的 `static contextType` 或 `Context.Consumer` 1. `useReducer`: 用于应对复杂的状态管理逻辑,类似于类组件中的 `setState` 1. `useRef`: 创建一个可变的 ref 对象,类似于类组件中的 `createRef`
Hooks 都可以帮助我们在函数式组件中实现类似于类组件的生命周期函数的功能
原文链接:https://juejin.cn/post/7362084722820546600