一、了解 react 组件的生命周期
- 什么是组件的生命周期:组件从被创建到挂载到页面中运行,再到组件不用时卸载的过程
- 钩子函数的作用:为开发人员在不同阶段操作组件提供了时机。
- 生命周期的意义:
- 有助于理解组件的运行方式
- 完成更复杂的组件功能
- 分析组件错误原因等
特别注意:只有
类组件才有生命周期
二、react 组件的生命周期钩子函数
1、挂载阶段
- 执行时机:组件创建时(页面加载时)
- 执行顺序:constructor()→ render()→ componentDidMount()
| 钩子函数 | 触发时机 | 触发时机 |
|---|---|---|
| constructor | 创建组件时,最先执行 | 1.初始化 state 1.创建 ref 等 |
| render | 每次组件渲染都会触发 | 渲染 UI (不能调用 setState() |
| componentDidMount | 组件挂载(完成DOM渲染)后 | 1. 发送网络请求 2.DOM操作 |
2、更新阶段
- 执行时机:1. setState() 2. forceUpdate() 3. 组件接收到新的 props
- 说明:以上三者任意一种变化,组件就会重新渲染
- 执行顺序:render()→ componentDidUpdate()
| 钩子函数 | 触发时机 | 作用 |
|---|---|---|
| render | 每次组件渲染都会触发 | 渲染 UI(与 挂载阶段 是同一个 render ) |
| componentDidUpdate | 组件更新(完成 DOM 渲染)后 | DOM 操作,可以获取到更新后的DOM内容,不要调用setState |
3、卸载阶段
- 执行时机:组件从页面中消失 钩子函数 | 触发时机 | 作用 | | -------------------- | ------------ | ----------------- | | componentWillUnmount | 组件卸载(从页面中消失) | 执行清理工作(比如:清理定时器等)
三、综合小小示例
1、创建项目、启动、新建文件夹及文件
- npx create-react-app react-circle
- cd react-circle
- yarn start 或 npm start 或 npm run start
- 新建 src/components/ComCircle.js
2、index.js 入口
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
)
3、App.js 导入组件
import React from 'react'
// 导入 ComCircle 组件
import ComCircle from './components/ComCircle'
class App extends React.Component {
render() {
return <div>
<ComCircle></ComCircle>
</div>
}
}
export default App
4.ComCircle.js 测试
-
需求:初始数据 100 ,设置按钮,点击每次加 100 ,加到 300 才更新页面,否则不更新
-
目标:探究生命周期钩子函数执行顺序
import React from 'react'
// react 生命周期钩子函数
class ComCircle extends React.Component {
// state 的写法 1
// ◆1. constructor 创建组件时,最先执行
constructor(){
super()
this.state = {
msg: '你好呀,ComCircle',
num:100
}
console.log(this.state.msg,'constructor');// 第一个打印
}
// state 的写法 2
// state = {
// msg: '你好呀,ComCircle',
// num: 100
// }
// ◆2. componentDidMount 相当于 v2 中的 mounted :DOM 加载完毕之后在触发,只会触发一次
componentDidMount() {
console.log(this.state.msg, 'componentDidMount');
}
// ◆3. componentDidUpdate 相当于 v2 中的 updated:初次进入不会触发
componentDidUpdate() {
console.log(this.state.msg, 'componentDidMount');
}
// ◆4. shouldComponentUpdate 判断组件是否应该更新了(这个只作了解,有替代方案)
shouldComponentUpdate(nextProps, nextState) {
console.log(nextProps, nextState, 'shouldComponentUpdate');
// 需要判断条件,return 一个 布尔值 不然会报错
// 满足条件就更新组件;否则不更新
return nextState.num === 300 ? true : false
}
// ◆5. componentWillUnmount 组件从页面消失,比如清理定时器等
componentWillUnmount() {
console.log('componentWillUnmount');
}
// 点击事件函数
changeHandler = () => {
// setState 的两个作用:1.修改 state;2.更新组件(UI)
this.setState({
num: this.state.num + 100
})
}
// ◆6. render 状态发生改变都会触发 render 函数(生命周期钩子函数)
render() {
console.log(this.state.msg, 'render');
return <div>
我是 ComCircle 组件
<p>数量:{this.state.num}</p>
<button onClick={this.changeHandler}>++100</button>
</div>
}
}
export default ComCircle
5、当点击按钮加到 400 后 ,页面及后台打印结果
法1:state 写在 constructor 里面
- 一进入页面
constructor、render、componentDidMount依次触发一次 - 点击按钮到 300 时
render、componentDidUpdate依次触发一次 - 点击按钮加到 400 及之后,
render、componentDidUpdate不再触发(因为shouldComponentUpdate里面有条件) componentWillUnmount没有触发,因为组件没有消失
法2:state 没有 写在 constructor 里面
- 一进入页面
render、componentDidMount依次触发一次 - 点击按钮到 300 时
render、componentDidUpdate依次触发一次 - 点击按钮加到 400 及之后,
render、componentDidUpdate不再触发(因为shouldComponentUpdate里面有条件) componentWillUnmount没有触发,因为组件没有消失
三、纯组件的引入
- 纯组件:
React.PureComponent与React.Component功能相似 - 区别:
PureComponent内部自动实现了shouldComponentUpdate钩子,不需要手动比较 - 原理:纯组件内部通过分别 对比 前后两次
props和state的值,来决定是否重新渲染组件 - 说明:纯组件内部的对比是 shallow compare(浅层对比)
- 值类型:比较两个值是否相同(直接赋值即可)
- 引用类型:只比较对象的引用地址是否相同
- 注意:只有在性能优化的时候可能会用到纯组件,不要所有的组件都使用纯组件,因为纯组件需要消耗性能进行对比
import React from 'react'
class ComCircle extends React.PureComponent {
render() {
return (
<div>纯组件</div>
)
}
}
export default ComCircle