完整的生命周期

我们都知道生命周期分为三个大阶段:

  1. 挂载
  2. 更新
  3. 卸载

挂载的时候我们我们有 constructor 、 getDerivedStateFromProps 、render 、 componentDidMount (即将被废弃的生命周期不再写入,也不推荐大家继续使用)

挂载

constructor

它一般用于初始化state和绑定事件,只有在这里对state赋值直接赋值,而且最好不要在这里进行副作用的操作,后面会做解释。还有不要将props直接赋值给state

  constructor(props) {
super(props);
this.state = {
name: this.props.name,
};
}


这种写法不会及时的更新状态

如下:

// 父组件
import React, {Component} from "react";
import Son from "./son"; class App extends Component {
constructor() {
this.state = {
number: 0,
};
}
render() {
const {number} = this.state;
return (
<div>
<button onClick={() => this.setState({number: number + 1})}>add</button>
<br/>
<Son name={this.state.number}/>
</div>
);
}
} export default App;
// 子组件
import React, {Component} from "react"; class Son extends Component {
constructor(props) {
super(props);
this.state = {
name: this.props.name,
};
} render() {
return (
<div>
<p>将props赋值给了子组件state</p>
{this.state.name}
<br/>
<p>直接使用了this.props.number</p>
{this.props.name}
</div>
);
}
} export default Son;

父组件点击一次以后,子组件中直接使用 this.props.number  的更新了,而通过赋值给state的没有更新。






-------------------------------------------------------------------------------------------------------------------**

getDerivedStateFromProps


-------------------------------------------------------------------------------------------------------------------

render

此方法在挂载阶段肯定会被调用,而在更新阶段会取决于 UNSAFE_componentWillUpdate和shouldComponentUpdate()返回值影响

它应该返回以下类型之一

  • React 元素。通常通过 JSX 创建。例如,<div /> 会被 React 渲染为 DOM 节点,<MyComponent /> 会被 React 渲染为自定义组件,无论是 <div /> 还是 <MyComponent /> 均为 React 元素。
  • 数组或 fragments。 使得 render 方法可以返回多个元素。欲了解更多详细信息,请参阅 fragments 文档。
  • Portals。可以渲染子节点到不同的 DOM 子树中。欲了解更多详细信息,请参阅有关 portals 的文档
  • 字符串或数值类型。它们在 DOM 中会被渲染为文本节点
  • 布尔类型或 null。什么都不渲染。(主要用于支持返回 test && <Child /> 的模式,其中 test 为布尔类型。)

componentDidMount

会在组件挂载到dom上的时候立即调用,如果这个时候调用setState的话会再次触发render,但是会在屏幕更新出来之前完成渲染。下面示例:

import React, {Component} from "react";

class SonTwo extends Component {
constructor(props) {
super(props);
this.state = {
number: 0,
};
} componentDidMount() {
this.setState({
number: this.state.number + 1,
});
} render() {
console.log("我执行了", this.state.number);
return (
<div>
{this.state.number}
</div>
);
}
} export default SonTwo;

![image.png](https://cdn.nlark.com/yuque/0/2020/png/425103/1586445215750-938b1066-9f85-4793-848f-81b1534faa69.png#align=left&display=inline&height=138&name=image.png&originHeight=138&originWidth=237&size=4367&status=done&style=shadow&width=237)


**这里为什么会出现4次,是因为 react的 **[**严格模式**](https://zh-hans.reactjs.org/docs/strict-mode.html#gatsby-focus-wrapper)

严格模式不能自动检测到你的副作用,但它可以帮助你发现它们,使它们更具确定性。通过故意重复调用以下函数来实现的该操作:

  • class 组件的 constructorrender 以及 shouldComponentUpdate 方法
  • class 组件的生命周期方法 getDerivedStateFromProps
  • 函数组件体
  • 状态更新函数 (即 setState 的第一个参数)
  • 函数组件通过使用 useStateuseMemo 或者 useReducer

所以使用的时候需要注意如果出现循环更改可能会出现性能问题

更新

getDerivedStateFromProps

shouldComponentUpdate

每次props或者state变化是render之前它会被调用,默认是正常调用render,但是如果这个周期函数返回false就会停止组件的渲染,不过父组件的state或者props变化不引起本组件改变,其子组件的state改变依然会更新

// 父组件
import React, {Component} from "react";
import Son from "./son"; class App extends Component {
constructor(props) {
super(props);
this.state = {
number: 0,
};
}
shouldComponentUpdate(nextProps, nextState, nextContext) {
return nextState.number > 10;
}
render() {
const {number} = this.state;
return (
<div style={{border: "1px solid red", margin: "6px"}}>
<button onClick={() => this.setState({number: number + 1})}>add
</button>
<br/>
<span>父组件中的number: </span>{this.state.number}
<br/>
<Son number={this.state.number}/>
{/*<SonTwo/>*/}
</div>
);
}
} export default App;
// 子组件
import React, {Component} from "react";
class Son extends Component {
constructor(props) {
super(props);
this.state = {
number: 0,
};
}
render() {
return (
<div style={{border: "1px solid blue", margin: "6px", padding: "20px"}}>
<button onClick={() => {
this.setState({
number: this.state.number + 1,
});
}}>ADD
</button>
<br/>
<br/>
<span>父组件中的值: </span>{this.props.number}
<br/>
<span>子组件中的值: </span>{this.state.number}
</div>
);
}
}
export default Son;

效果如图:


   


图1 是点击了外层的父节点的add后子节点并没接收到父节点传递过来的值,因为父节点的render并没有被触发。

图2 是点击了内层的子节点上ADD后发现子组件触发了render

-------------------------------------------------------------------------------------------------------------------**

render

同上

-------------------------------------------------------------------------------------------------------------------

getSnapshotBeforeUpdate

componentDidUpdate

在更新结束和被调用,首次渲染不会触发它,首次渲染触发的 componentDidMount 可以做的 DOM 操作或者发起请求,它也可以,只是更新渲染结束后不会再触发componentDidMount, 而触发的是它。可以基于更新前后的state或者props的变化来做出相应的请求或者操作




重点对于状态的更改需要做出判断

你也可以在 componentDidUpdate() 中直接调用 setState(),但请注意它必须被包裹在一个条件语句里,正如上述的例子那样进行处理,否则会导致死循环。


-------------------------------------------------------------------------------------------------------------------**

卸载

componentWillUnmount

componentWillUnmount() 会在组件卸载及销毁之前直接调用。在此方法中执行必要的清理操作,例如,清除 timer,取消网络请求或清除在 componentDidMount() 中创建的订阅等。

componentWillUnmount()不应调用 setState(),因为该组件将永远不会重新渲染。组件实例卸载后,将永远不会再挂载它。

最新文章

  1. android清除本应用里的各种数据的方法
  2. vue-loader配合webpack的使用及安装
  3. 查看cpu
  4. PHPWord
  5. Leetcode Minimum Path Sum
  6. js String Trim函数
  7. &lt;八&gt;面向对象分析之UML核心元素之分析类
  8. iOS开发之状态栏UIStatusBar图标操作
  9. What&#39;s the use of @ before the path defination
  10. hadoop hdfs 命令行 设置文件夹大小的上限 quota:配额
  11. java eclipse 连接数据库全过程
  12. ExtJs4得知(五岁以下儿童)主要的Ext分类
  13. Hibernate 系列教程6-双向多对多
  14. 201521123115 《Java程序设计》第1周学习总结
  15. 武汉倍特威视系统有限公司 --- 安全帽识别|烟火识别|智慧工地|BVS智能视频分析
  16. P3203 [HNOI2010]弹飞绵羊 —— 懒标记?分块?LCT?...FAQ orz
  17. linux c++ curl https 请求并双向验证SSL证书
  18. [wx]雪落香杉树人物关系图
  19. R语言——实验5-聚类分析
  20. 在eclipse里配置Android ndk环境 适用于windows mac 和linux(转)

热门文章

  1. Word16 供应链的管理论文office真题
  2. npm发包
  3. vue 学习 css第四天
  4. pycharm的基本操作数据类型
  5. JavaScript 静态方法
  6. golang json 字符串 用 json.Number 解析字段
  7. 如何将视频作为Windows桌面动态壁纸,两步就可以搞定!
  8. Ubuntu20.04 LTS更新源
  9. 10个.NetCore实用的开源框架项目
  10. webpack的加载器兼容配置一览