重识React — — 与生命周期叙叙旧
前言
在2023年3月29日,React 18正式发布了,较之React 17,又带来了极为重磅的新特性,比如:
ReactDOM.createRoot
,支持并发模式的渲染。- 支持
setState
自动批处理,将多个状态的更新批量处理,合并成一次更新。 - ....
咳咳,好像扯远了🤐,今天咱不是来聊React 18的。年轻的React 18站在Facebook大堂的舞台中心,无数的目光聚焦于她,一阵又一阵赞叹的声浪从四面八方涌向舞台,此起彼伏的人群中隐约可见一对互相依偎的身影,她们定定地望向舞台,目光里只有欣慰,她们是React 15 和React 16。
React 15的生命周期
穿过热闹的人群,我走到她们的面前,站在右边的我认识,是React 16,她向我道了声好,算是久别重逢后的寒暄。站在左边的那位我虽然并不认识,但是开动脑筋想一想,也知道定是React 15了。
React 15是2016年推出的,那时候我还在高中写《五年高考三年模拟》呢,认不出来也是自然的。
React 15显得很热情,许是太久没和新面孔相遇了,招呼我再向她走近些儿,给我看了一张照片,一张足以道尽她的一生的照片。
名为“生命周期”的照片
-
constructor()
-
componentWillReceiveProps()
-
shouldComponentUpdate()
-
componentWillMount()
-
componentWillUpdate()
-
componentDidUpdate()
-
componentDidMount()
-
render()
-
componentWillUnmount()
这些字符凑在一起,像是一篇晦涩难懂的英语阅读理解😣,我的目光游移,实在难以聚焦,下意识地将照片翻过面来,凑巧地看到照片背面的那一行小字:“照着口诀念念看吧~”
“1个周期,3个阶段!”
刚念完口诀,照片背面竟显现出一幅流程图,我从来没有想到有一天看流程图能看出亲切感来😭...
结合这图,我算是明白了个大概,但是对于生命周期的执行顺序是否如图中所示般固定,还是没什么底。
React 15见我还是眉头紧皱,便体贴地说道:“小同学,不妨让我用JSX给你写几个Demo,帮助你理解吧?JSX你应该很熟了吧~”
我心虚地点点头:“哈哈...是挺熟的,麻烦了🙏”(昨天刚熟也算熟吧)
Demo
父组件
import React from "react";
import LifeCycle from "./life-cycle";
class FatherOfLifeCycle extends React.Component<{}, any> {
state: { text: string; hideChild: boolean } = {
text: "父组件的文本",
hideChild: false,
};
changeText = () => {
this.setState({ text: "我是发生修改后的父组件文本" });
};
hideChildren = () => {
this.setState({ hideChild: true });
};
render(): React.ReactNode {
return (
<div className="fatherContainer">
<button onClick={this.changeText} className="changeText">
点击修改父组件文本内容
</button>
<button onClick={this.hideChildren} className="hideChildren">
隐藏子组件内容
</button>
{this.state.hideChild ? null : <LifeCycle text={this.state.text} />}
</div>
);
}
}
export default FatherOfLifeCycle;
子组件
import React, { ReactDOM } from "react";
class LifeCycle extends React.Component<{ text: string }, any> {
constructor(props: any) {
console.log("进入constructor");
super(props);
this.state = { text: "子组件的文本" };
}
componentWillMount(): void {
console.log("componentWillMount执行");
}
componentDidMount(): void {
console.log("componentDidMount执行");
}
componentWillReceiveProps(nextProps: any, nextContext: any): void {
console.log("componentWillReceiveProps执行");
}
shouldComponentUpdate(
nextProps: any,
nextState: any,
nextContext: any
): boolean {
console.log("shouldComponentUpdate执行");
return true;
}
componentWillUpdate(nextProps: any, nextState: any, nextContext: any): void {
console.log("componentWillUpdate执行");
}
componentDidUpdate(prevProps: any, prevState: any, snapshot?: any): void {
console.log("componentDidUpdate执行");
}
componentWillUnmount(): void {
console.log("子组件的componentWillUnmount执行");
}
changeText = () => {
this.setState({ text: "我是发生修改后的子组件文本" });
};
render(): React.ReactNode {
console.log("render方法执行");
return (
<div className="container">
<button onClick={this.changeText} className="changeText">
点击修改子组件文本内容
</button>
<p>子组件文本内容:{this.state.text}</p>
<p>父组件文本内容:{this.props.text}</p>
</div>
);
}
}
export default LifeCycle;
请忽略博主对于“Anyscript”的使用,以及时间紧凑,丑丑的css样式🥲
Mounting 组件的初始化渲染(挂载)
挂载只会在组件的一生中发生1次。
-
注意🔈:☝️这里的
render()
在执行过程中并不会去操作真实DOM,而仅仅是把需要渲染的内容返回出来 -
挂载阶段真实DOM的渲染工作是由
ReactDOM.render()
承接的。 -
componentDidmount()
方法在渲染结束后被触发,这也意味是真实DOM已经挂载到了页面上,于是我们就可以在这个生命周期里执行真实DOM相关的操作
Updating
提问❓:☝️这里的componentWillReceiveProps()
到底是由什么触发的?
回答:
如果父组件导致组件重新渲染,即使props没有更改,也会调用此方法。
如果只想处理更改,请确保进行当前值与变更值的比较
—— React官方
也就是说,componentWillReceiveProps()
并不是由props的变化触发的,而是由父组件的更新触发的。
也是因此,当父组件因为其他与子组件无关的属性变化导致更新时,我们期望避免这种对子组件不必要的渲染的发生,因此React提供给了我们shouldComponentUpdate()
。
React组件会根据shouldComponentUpdate()
的返回值来决定是否接着执行该方法之后的生命周期,进而决定是否对组件进行re-render。
因此,除了避免不需要的渲染发生,我们也可以往其中加一些判定条件,来主动实现一些我们期望的渲染发生。退可守也进可攻。
思考❓:那么PureComponent
是不是也是上述功能的一种体现呢?
期待你在评论区的留言👀
Unmounting
组件销毁的常见原因,有以下两个:
- 组件在父组件中被移除了
- 组件中设置了key属性,父组件在render的过程中,发现key值和上一次不一致
好用,但又没那么好用
在React 15的自我介绍下,我大致上是明白了。但是一路听下来,有两个地方觉得不太对劲,componentWillMount()
和componentWillUpdate()
两兄弟好像有点多余?如同给手机套了两层手机壳,手机摔地上时,确实会比套一层的手机受伤小一点,但是仅仅为了这微小的提升,导致整机多了一倍的重量,算来算去都觉得不划算啊。
我将这个疑问与她们分享,React 16听完后对我是又好气又好笑,抱怨道:“你之前用了这么久的React 16,难道不觉得componentWillMount()
和componentWillUpdate()
从来都没见过吗!”
我一拍脑袋,确实啊,为什么React 16里没有它们了呢?
React 16也拍了拍我的脑袋,然后清了清嗓子,一副早就有话要说的样子...
后言
还剩10分钟不到,就要过凌晨12点啦,每日一文可不能断咯😩。因为今日周一加班比较晚,所以本文的内容有些仓促,也有很多不足(下次一定修改)。 那就先聊到这里吧,我是海石,我们明天见~
转载自:https://juejin.cn/post/7269691627598954511