文章目录
- 前言
- 一、类组件的生命周期
- 1、什么是类组件
- 2、生命周期钩子
- 二、函数组件生命周期
- 1、什么是函数组件
- 2、模拟类组件生命周期钩子
- 三、为什么要使用生命周期
- 1、我们能在钩子里面干什么
- 2、PureComponent和React.memo区别
- 总结
前言
最近在写react项目,所以一直想写函数组件和类组件生命周期相关的一些知识总结。
基础知识,仅用来复习,和巩固学习。
一、类组件的生命周期
1、什么是类组件
类组件是使用ES6中关键字class来定义。类组件具有特定的生命周期方法,可以在不同阶段执行一些操作。类组件中必须实现render()方法来描述组件界面,并且可以通过state属性来存储和管理组件的内部状态。
例如:
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
state1: 'This is a React class.'
};
}
render() {
return (
<div>{state1}</div>
);
}
}
这就是一个最基本的react类组件。
2、生命周期钩子
- 定义:
生命周期函数是react类组件在整个组件从创建到卸载各个阶段自动调用的钩子函数。 - 有哪些钩子及钩子的基本作用:
//挂载阶段:组件被创建并插入到DOM中
constructor():
组件初始化时调用,用于初始化state和绑定方法
static getDerivedStateFromProps():
在组件挂载前和更新前调用,用于更新state
render():
必须定义,创建虚拟DOM并返回JSX结构
componentDidMount():
组件挂载后调用,可以进行DOM操作和网络请求等异步操作
//更新阶段:组件的props或state发生改变时触发
static getDerivedStateFromProps():
在组件挂载前和更新前调用,用于更新state
shouldComponentUpdate():
在组件更新前调用,用于判断组件是否需要更新
render():
必须定义,创建虚拟DOM并返回JSX结构
getSnapshotBeforeUpdate():
在组件更新前调用,用于获取DOM快照(如滚动位置等)
componentDidUpdate():
在组件更新后调用,可以进行DOM操作和网络请求等异步操作
//卸载阶段:组件从DOM中移除
componentWillUnmount():
在组件卸载前调用,用于清理组件相关的资源
示例代码:
//App组件-由于太懒了就直接用函数组件写了
import React, { useState } from 'react'
import TestLifeCycle from './pages/testLifeCycle'
const App = () => {
const [show, setShow] = useState(true)
const unMountClick = () => {
setShow(!show)
}
return (
<div className="App">
{ show ? <TestLifeCycle/> : null }
<button onClick={unMountClick}>卸载</button>
</div>
)
}
export default App
//TestLifeCycle组件
import React from "react";
class TestLifeCycle extends React.Component {
constructor () {
console.log('constructor---')
super()
this.state = {
state1: 'This is a React class.'
}
}
componentDidMount() {
console.log('componentDidMount---')
}
//更新
static getDerivedStateFromProps(props, state) {
console.log('getDerivedStateFromProps---', props, state)
return null
}
shouldComponentUpdate(nextProps, nextState) {
console.log('shouldComponentUpdate---', nextProps, nextState)
return true
}
getSnapshotBeforeUpdate(prevProps, prevState) {
console.log('getSnapshotBeforeUpdate---', prevProps, prevState)
return null
}
componentDidUpdate() {
console.log('componentDidUpdate---')
}
//卸载
componentWillUnmount() {
console.log('componentWillUnmount---')
}
updateState = () => {
this.setState({
state1: 'This is a React class. updateState'
})
}
render () {
const { titleShow } = this.state
console.log('render---')
return (
<>
<div>{this.state.state1}</div>
<button onClick={this.updateState}>更新</button>
</>
)
}
}
export default TestLifeCycle
首次运行后可以看到控制台打印的内容是:
当点击更新按钮更新state的时候可以看到打印了这些
当我们点击卸载按钮的时候看到正常打印了卸载的钩子函数
可以看到钩子函数还是很多的,可以让我们在不同的阶段不同的钩子函数里面实现很多业务逻辑。
二、函数组件生命周期
1、什么是函数组件
函数组件是一种声明式方式定义组件的形式,使用function关键字来定义一个新的函数。函数组件被设计成无状态的,只以props作为输入并返回React元素作为输出。函数组件不需要实现类组件中的生命周期方法和state状态。
例如:
import React, { useState } from 'react'
import TestLifeCycle from './pages/testLifeCycle'
const App = () => {
const [show, setShow] = useState(true)
const unMountClick = () => {
setShow(!show)
}
return (
<div className="App">
{ show ? <TestLifeCycle/> : null }
<button onClick={unMountClick}>卸载</button>
</div>
)
}
export default App
2、模拟类组件生命周期钩子
因为函数组件没有生命周期钩子函数,所以我们只能是做一个模拟
可以模拟最基本的三个阶段钩子
import { useEffect, useState } from 'react'
function TestLifeCycleHook() {
const [state, setState] = useState('This is function Hook.')
// 模拟 componentDidMount 方法
useEffect(() => {
console.log('模拟---componentDidMount---')
}, []);
// 模拟 componentDidUpdate 方法
useEffect(() => {
console.log('模拟---componentDidUpdate---', state);
}, [state]);
// 模拟 componentWillUnmount 方法
useEffect(() => {
return () => {
console.log('模拟---componentWillUnmount---');
};
}, []);
const updateState = () => {
setState('This is function Hook. updateState')
}
return (
<>
<div>{state}</div>
<button onClick={updateState}>更新state</button>
</>
)
}
export default TestLifeCycleHook
首次运行我们可以看到控制台
当点击更新和卸载按钮的时候
三、为什么要使用生命周期
1、我们能在钩子里面干什么
因为这些钩子函数会在组件不同的生命周期阶段自动调用,所以:
- 我们可以在我们想要的时候根据实际的业务逻辑实现一些特定的功能。例如:
constructor:设置状态(State)和绑定方法(bind methods)。
componentDidMount:从服务器获取数据,调用接口。
componentDidUpdate:根据 props 和 state 的变化更新数据。
componentWillUnmount:清理数据,或者清楚定时器等异步任务。
shouldComponentUpdate:是优化组件必备的一个函数,可以使用它内部传入的参数决定是否需要重新渲染组件dom。—但是这个函数我们也可以使用react提供的PureComponent。优化性能必备。
class TestLifeCycle extends PureComponent
getDerivedStateFromProps:该函数在组件每次 render 前调用,它可以根据 props 计算 state,并返回一个对象来更新 state,或者返回 null 来表示不需要更新 state。
getSnapshotBeforeUpdate:该函数在组件即将更新和重新渲染之前调用,它返回一个 snapshot(快照),这个快照会在 componentDidUpdate() 函数中作为第三个参数传入使用。在这个函数内部可以读取 DOM 中的值,然后通过返回一个对象将值传递到 componentDidUpdate() 函数中。
- 注意
自 React 16.3 版本以来,React 官方已经废弃了以下三个生命周期钩子函数:
componentWillMount()
componentWillReceiveProps(nextProps)
componentWillUpdate(nextProps, nextState)
替代方案:
用 constructor() 函数代替 componentWillMount()
用 static getDerivedStateFromProps() 或 componentDidUpdate() 来代替 componentWillReceiveProps()
用 (PureComponent)shouldComponentUpdate() 或 React.memo() 取代 componentWillUpdate()
2、PureComponent和React.memo区别
(PureComponent)shouldComponentUpdate() 或 React.memo()区别
总结
有了函数组件我认为新的项目还是应该用hooks去编写,相比于类组件
函数式组件比类组件更简洁,不必在组件内部声明构造函数和 render 方法等
Hook 是 React 16.8 引入的新特性,它可以让函数式组件具备类组件所具备的状态和生命周期功能
虽然函数组件有这么多优点,但是官方也不会放弃类组件,所以我个人认为可以在大型项目根据实际情况,混用类组件与和函数组件。但是新手不建议这么使用。
如果有问题欢迎指正