内容简介:如果将组件比作我们图中的:ant:,吊绳比作:ant:(组件)的寿命,吊绳左端表示:ant:的出生(组件的创建),右端表示:ant:的死亡(组件的销毁)。:ant:从生到死的过程会触发吊牌上的钩子函数执行,在挂载:将虚拟DOM转化为真实DOM的过程组件挂载之前,在渲染过程中可能会执行多次,不推荐使用
前言
如果将组件比作我们图中的:ant:,吊绳比作:ant:(组件)的寿命,吊绳左端表示:ant:的出生(组件的创建),右端表示:ant:的死亡(组件的销毁)。:ant:从生到死的过程会触发吊牌上的钩子函数执行,在 React 中我们把组件从创建到销毁的过程中需要触发的钩子函数称之为生命周期函数
React 生命周期
旧版
初始化阶段( Initalization )
-
setup props ande state(设置组件的初始化属性和状态)
初始化状态对象
static defaultProps = {
name:'计数器' //初始化默认的属性对象
}
复制代码
初始化属性对象
constructor(props){
super(props);
this.state = {
number:0
}
}
复制代码
挂载阶段( Mounting )
挂载:将虚拟DOM转化为真实DOM的过程
componentWillMount
组件挂载之前,在渲染过程中可能会执行多次,不推荐使用
render
组件挂载
componentDidMount
组件挂载之后,永远只会执行一次,推荐在此阶段执行副作用,进行异步操作。比如发 ajax 请求,操作 DOM 等
更新阶段( Updation )
属性更新(props变化)
componentWillReceiveProps
组件收到新的属性对象时调用,首次渲染不会触发
shouldComponentUpdate
询问组件是否可以更新
- 参数:新的属性对象
- 返回:
boolean值true false
componentWillUpdate
组件更新之前
render
根据新的属性对象重新挂载(渲染)组件
componentDidUpdate
组件更新完成
状态更新(state变化)
shouldComponentUpdate
询问组件是否可以更新
- 参数:新的状态对象
- 返回:
boolean值true false
componentWillUpdate
组件更新之前
render
根据新的状态对象重新挂载(渲染)组件
componentDilUpdtae
组件更新完成
卸载阶段( Unmounting )
componentWillUnmount
组件卸载之前调用
放码过来
有兴趣的朋友可以根据以下代码进行测试
import React, { Component } from 'react';
/**
* 父组件
*/
class Counter extends Component {
static defaultProps = { //初始化默认的属性对象
name:'计数器'
}
constructor(props) {
super(props);
this.state = { // 初始化默认的状态对象
number:0
}
console.log('1. 父constructor初始化 props and state');
}
componentWillMount() {
console.log('2. 父componentWillMount组件将要挂载');
}
componentDidMount() {
console.log('4. 父componentDidMount组件挂载完成');
}
shouldComponentUpdate() {
console.log('5. 父componentShouldUpdate询问组件是否可以更新');
return true;
}
componentWillUpdate() {
console.log('6. 父componentWillUpdate组件将要更新');
}
componentDidUpdate() {
console.log('7. 父componentDidUpdate组件更新完成');
}
render() {
console.log('3. 父render渲染,也就是挂载');
const style = {display:'block'}
return (
<div style={{border:'10px solid green',pending:'10px'}}>
{this.props.name}:{this.state.number}
<button onClick={this.add} style={style}>+</button>
{this.state.number %3 !== 0 && <SubCounter number={this.state.number}/>}
</div>
);
}
add = () => {
this.setState({
number:this.state.number+1
})
}
}
/**
* 子组件
*/
class SubCounter extends Component {
static defaultProps = {
number:10
}
componentWillReceiveProps() {
console.log('1. 子componentWillReceiveProps属性将要发生变化 ');
}
shouldComponentUpdate(nextProps, nextState) {
console.log('2. 子componentShouldUpdate询问组件是否可以更新');
// 调用此方法的时候会把新的属性对象和新的状态对象传递过来
if (nextProps.number % 3 === 0) {
return true;
}
return false;
}
componentWillUnmount() {
console.log(' 3.子componentWillUnmount组件将要卸载 ');
}
render() {
return (
<div style={{border:'10px solid red'}}>
{this.props.number}
</div>
);
}
}
export default Counter;
复制代码
新版
创建时
constructor
初始化属性和状态
getDerivedStateFromProps
根据属性对象派生状态对象
- 静态方法
- 参数:新的属性对象,旧的状态对象
- 用途:在没有这个生命周期函数之前,我们使用的数据来源可能是属性对象,也可能是状态对象,在我们的上文中的 放码过来 阶段就有所体现,我们可以通过这个生命周期函数将属性对象派生到状态对象上,使我们在代码中只通过
this.state.XXX来绑定我们的数据。示例如下
import React, { Component } from 'react';
/**
* 父
*/
class Counter extends Component {
constructor(props) {
super(props);
this.state = {
number:0
}
}
render() {
return (
<div>
<p>{this.state.number}</p>
<button onClick={this.add}>+</button>
<SubCounter number={this.state.number}/>
</div>
);
}
add = () => {
this.setState({
number:this.state.number+1
})
}
}
/**
* 子
*/
class SubCounter extends Component {
constructor(props) {
super(props);
this.state = {
number:0
}
}
static getDerivedStateFromProps(nextProps, prevState) {
if (nextProps.number % 2 === 0) {
return {number:nextProps.number*2}
} else {
return {number:nextProps.number*3}
}
}
render() {
console.log(this.state);
return (
<div>
<p>{this.state.number}</p>
</div>
);
}
}
export default Counter;
复制代码
render
挂载(渲染)组件
componentDidMount
组件挂载(渲染)完成
更新时
getDerivedStateFromProps
根据属性对象派生状态对象
- 静态方法
- 参数:新的属性对象,旧的状态对象
shouldComponentUpdate
询问组件是否可以更新
- 参数:新的状态对象
- 返回:
boolean值true false
render
根据新的状态对象重新挂载(渲染)组件
getSnapshotbeforeUpdate
获取更新前的快照
- 举例:在我们的日常开发中你一定会遇到这个问题,异步加载资源,当浏览器处于非第一屏的时候并且所在屏之前的模块并没有加载出来,你肯定不希望在所在屏之前的模块加载出来之后浏览器显示窗口仍然处于当前的高度,而是希望仍然处于我们所浏览屏的高度,在没有这个生命周期之前
react处理这个问题是很棘手的。
未使用 getSnapshotbeforeUpdate
import React, { Component } from 'react';
class GetSnapshotBeforeUpdate extends Component {
constructor(props) {
super(props);
this.wrapper = React.createRef();
this.state = {
messages:['4','3','2','1','0']
}
}
componentDidMount() {
setInterval(() => {
this.setState(() => {
this.state.messages.unshift(this.state.messages.length);
}, () => {
this.setState({
messages: this.state.messages
})
})
},1000)
}
render() {
let style = {
height: '100px',
width: '200px',
border: '1px solid red',
overflow:'auto'
}
return (
<ul style={style} ref={this.wrapper}>
{
this.state.messages.map((message, index) => <li key={index}>{message}</li>)
}
</ul>
);
}
}
export default GetSnapshotBeforeUpdate;
复制代码
使用 getSnapshotbeforeUpdate
import React, { Component } from 'react';
class GetSnapshotBeforeUpdate extends Component {
...
getSnapshotBeforeUpdate() {
// 返回更新内容的高度
return this.wrapper.current.scrollHeight;
}
// 组件更新完毕
componentDidUpdate(prevProps,prevState,prevScrollHeight) {
console.log(prevProps,prevState,prevScrollHeight);
this.wrapper.current.scrollTop = this.wrapper.current.scrollTop +
(this.wrapper.current.scrollHeight - prevScrollHeight);
}
...
export default GetSnapshotBeforeUpdate;
复制代码
componentDidUpdate
组件更新完成
卸载时
componentWillUnmount
组件卸载之前
以上所述就是小编给大家介绍的《React生命周期》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。