一、什么是生命周期函数?
React 组件也有自己的生命周期,了解组件的生命周期可以让我们在最合适的地方完成自己想要的功能;
二、生命周期和生命周期函数的关系
注意: 函数式组件没有生命周期函数,但可以通过 useEffect(React v16.8) 模拟生命周期函数
三、React 16 前的生命周期函数
1. 组件初始化(Initialization)阶段
首先是Initialization,初始化state和props的数据,也就是类的构造方法 constructor(), Test 类继承了 React.Component 这个基类,也就继承这个 React 的基类,才能有 render() ,生命周期等方法可以使用,这也说明为什么 函数组件不能使用这些方法的原因
constructor中通常只做两件事情:
-
通过给 this.state 赋值对象来初始化内部的state;
-
为事件绑定实例(this);
class Test extends React.Component {
constructor(props) {
super(props);
this.state = {
first: 1
};
this.handleClick = this.handleClick.bind(this);
}
}
如果不初始化 state 或不进行方法绑定,则不需要为 React 组件实现构造函数
import { Component } from "react";
import "./App.css";
function App() {
return <Test content="hello"></Test>;
}
class Test extends Component {
render() {
return <span>{this.props.content}</span>;
}
}
export default App;
在上面代码中我并没有初始化 this.props,但是还可以正常调用,那是因为在 React 源码中,帮助我们初始化了 this.props
2. 组件的挂载(Mounting)阶段
- componentWillMount
- render
- componentDidMount
2.1 componentWillMount
React v16 弃用
2.2 render
2.3 componentDidMount
常用操作:
- 依赖于DOM的操作可以在这里进行;
- 在此处发送网络请求就最好的地方(官方建议);
- 可以在此处添加一些订阅(会在componentWillUnmount取消订阅);
3. 组件的更新(Updation)阶段
- componentWillReceiveProps
- shouldComponentUpdate
- componentWillUpdate
- render(这里只是重新调用)
- componentDidUpdate
在讲述此阶段前需要先明确下 react 组件更新机制。setState引起的 state 更新或父组件重新 render 引起的 props 更 新,更新后的 state 和 props 相对之前无论是否有变化,都将引起子组件的重新 render。
3.1 造成组件更新情况
1. 每当父组件重新 render 导致的重传 props,子组件将直接跟着重新渲染,无论 props 是否有变化。
可通过 shouldComponentUpdate,或者继承 PureComponent 类方法优化,函数式组件可以使用 memo() 包裹
class Child extends Component {
shouldComponentUpdate(nextProps) {
// 应该使用这个方法,否则无论props是否有变化都将会导致组件 跟着重新渲染
if(nextProps.someThings === this.props.someThings) {
return false
}
}
render() {
return <div>{this.props.someThings}</div>
}
}
2. 组件本身调用 setState,无论 state 有没有变化。
可通过 shouldComponentUpdate,或者继承 PureComponent 类方法优化,函数式组件可以使用 memo() 包裹
class Child extends Component {
constructor(props) {
super(props);
this.state = { someThings: 10 };
}
shouldComponentUpdate(nextProps, nextState) {
// 应该使用这个方法,否则无论state是否有变化都将会导致组件重新渲染
if (nextState.someThings === this.state.someThings) {
return false;
}
return true;
}
handleClick = () => {
// 虽然调用了setState ,但state并无变化
const preSomeThings = this.state.someThings;
this.setState({ someThings: preSomeThings });
};
render() {
return <div onClick={this.handleClick}>{this.state.someThings}</div>;
}
}
3.2 shouldComponentUpdate(nextProps, nextState)
// nextProps 更新后的 props 的值
// nexState 更新后的 state 的值
shouldComponentUpdate(nextProps, nextState) {
// nextState.someThings 更新后的数据
// this.state.someThings 当前数据
// 判断前后数据是否相同
if (nextState.someThings === this.state.someThings) {
// 不更新
return false;
}
// 更新
return true;
}
注意: shouldComponentUpdate 内部不推荐使用深比较,因为使用 shouldComponentUpdate 比较的目的是为了减少 render 的执行,render 执行会创建虚拟 DOM,新老 DOM 进行比较(diff 算法),从而提高性能,但是深比较的时间可能会比 diff 算法的时间更长,所以不推荐使用深比较
3.3 ccomponentWillUpdate(nextProps, nextState)
React v16 弃用
3.4 componentDidUpdate(prevProps, prevState)
常用操作:
- 当组件更新后,可以在此处对 DOM 进行操作;
- 如果你对更新前后的 props 进行了比较,也可以选择在此处进行网络请求;(例如,当 props 未发生变化时,则不会执行网络请求)
注意: 在 React v16.4 componentDidUpdate 新增了第三个参数
componentDidUpdate(prevProps, prevState, snapshot)
如果组件实现了 getSnapshotBeforeUpdate() 生命周期(不常用),则它的返回值将作为 componentDidUpdate() 的第三个参数 “snapshot” 参数传递。否则此参数将为 undefined
3.5 componentWillReceiveProps(nextProps)
此方法只调用于props引起的组件更新过程中,参数nextProps是父组件传给当前组件的新props。但父组件render 方法的调用不能保证重传给当前组件的props是有变化的,所以在此方法中根据nextProps和this.props来查明重传 的props是否改变,以及如果改变了要执行啥,比如根据新的props调用this.setState出发当前组件的重新render
React v16 弃用
4. 组件的卸载(Unmounting)阶段
- componentWillUnmount
4.1 componentWillUnmount
常用于清理操作: 清除 timer,取消网络请求或清除在 componentDidMount() 中创建的订阅等
四、React v16.4 的生命周期
React v16.4 的生命周期图
1. 变更原因
React 以前是同步更新,如果更新的组件过多,就会阻塞线程,用户有操作无法立即响应,界面卡顿,影响用户体验。然后React v16推出的 React Fiber, 原来(React v16.0前)的生命周期再 React Fiber后就不合适了, 在 render 函数执行之前的所有函数都有可能执行多次。
(React v16.0前)在render前执行的生命周期
- componentWillMount
- componentWillReceiveProps
- shouldComponentUpdate
- componentWillUpdate
禁止不能用比劝导开发者不要这样用的效果更好,所以除了 shouldComponentUpdate,其他在render函数之前的所有函数(componentWillMount,componentWillReceiveProps,componentWillUpdate)都被 getDerivedStateFromProps替代。
也就是用一个静态函数 getDerivedStateFromProps 来取代被过去的几个生命周期函数,就是强制开发者在render之前只做无副作用的操作,而且能做的操作局限在根据 props 和 state 决定新的 state
React v16.0刚推出的时候,是增加了一个componentDidCatch生命周期函数,这只是一个增量式修改,完全不影响原有生命周期函数;但是,到了React v16.3,大改动来了,引入了两个新的生命周期函数。
2. 新引入了两个新的生命周期函数: getDerivedStateFromProps , getSnapshotBeforeUpdate
2.1 getDerivedStateFromProps
getDerivedStateFromProps 本来(React v16.3中)是只在创建和父组件触发更新,getDerivedStateFromProps 才会被调用,不能被自身 setState 引发或者 forceUpdate 触发。
这样的话理解起来有点乱,在React v16.4中改正了这一点,让getDerivedStateFromProps 无论是 Mounting 还是 Updating,也无论是因为什么引起的 Updating,全部都会被调用,具体可看React v16.4 的生命周期图。
React v16.4后的
static getDerivedStateFromProps(props, state)
在组件创建时和更新时的render方法之前调用,它应该返回一个对象来更新状态,或者返回 null 来不更新任何内容。
getDerivedStateFromProps 的存在只有一个目的:让组件在 props 变化时更新 state
class Test extends React.Component {
super(props);
this.state = {
num: 20,
sum: 100,
};
}
static getDerivedStateFromProps(props, state) {
// return null;
return {
num: 60,
};
}
render() {
return (
<>
<div>{this.state.num}</div> {/* 60 */}
<div>{this.state.sum}</div> {/* 100 */}
</>
);
}
}
2.2 getSnapshotBeforeUpdate
getSnapshotBeforeUpdate(prevProps, prevState)
getSnapshotBeforeUpdate() 在最近一次渲染输出(提交到 DOM 节点)之前调用。它使得组件能在发生更改之前从 DOM 中捕获一些信息(例如,滚动位置)。此生命周期的任何返回值将作为参数传递给 componentDidUpdate()。
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!