react组件设计原则_一入React深似海(一) LifeCycle

为什么React16要更改组件的生命周期?

我将抱着帮你做到“知其所以然”的目的,以 React 的基本原理为引子「我将抱着帮你做到“知其所以然”的目的,以 React 的基本原理为引子,对 React 15、React 16 两个版本的生命周期进行探讨、比对和总结,通过搞清楚一个又一个的“Why”,来帮你建立系统而完善的生命周期知识体系。」

生命周期背后的设计思想:把握React中的“大方向”

在介绍具体的生命周期之前,我想先带着你初步了解 React 框架中的一些关键的设计思想,以便为你后续的学习提供不可或缺的“加速度”。

如果你经常翻阅 React 官网的文章,你会发现**“组件”和“虚拟DOM”** 这两个词的出镜率是非常高,它们是 React 基本原理中极为关键的两个概念,也是我们这次深入学习生命周期的切入点。

虚拟DOM: 核心算法的基石

在jsx部分,我们已经知道了虚拟DOM的基本形态(不太了解的可以先翻阅前一篇文章)。我们需要简单了解下虚拟 DOM 在整个 React 工作流中的作用。

组件在初始化时,会调用生命周期中的 render 方法,「生成虚拟DOM」 ,然后再通过 「ReactDOM.render」 方法,实现虚拟DOM到真实DOM的转换

当组件更新时,会再次通过 render 方法生成 「新的虚拟DOM」,然后借助 「diff」(这是一个非常关键的算法,后面我会专门讲解)「定位出两次虚拟DOM的差异」,从而针对发生变化的真实DOM做定向更新

以上就是React 框架算法的大致流程,对于这套关键的工作流来说,「“虚拟DOM”」 是所有操作的大前提,是核心算法的基石。

组件化:工程化思想在框架中的落地

组件化是一种优秀的软件设计思想,也是 React 团队在研发效能方面所做的一个重要的努力。

在一个 React 项目中,几乎所有的可见/不可见的内容都可以被抽离为各种各样的组件,每个组件既是“封闭”的,也是“开放”的。

所谓“封闭”,主要是针对“渲染工作流”(指从组件数据改变到组件实际更新发生的过程)来说的。在组件自身的渲染工作流中,每个组件都只处理它内部的渲染逻辑。在没有数据流交互的情况下,组件与组件之间可以做到“各自为政”。

而所谓“开放”,则是针对组件间通信来说的。React 允许开发者基于“单向数据流”的原则完成组件间的通信。而组件之间的通信又将改变通信双方/某一方内部的数据,进而对渲染结果构成影响。所以说在数据这个“红娘”的牵线搭桥之下,组件之间又是彼此开放的,是可以相互影响的。

这一“开放”与“封闭”兼具的特性,使得 React 组件既专注又灵活,具备高度的可重用性和可维护性。

生命周期方法的本质:组件的“灵魂”与“躯干”
  • 「render方法为React组件的灵魂」
  • 「其他生命周期方法为躯干」

注意:这里提到的render 方法,和之前说的 「ReactDOM.render」 不是一个东西,它指的是 React 组件内部的这个生命周期方法:

class LifeCycle extends React.Component {
     
    render() {
        console.log("render方法执行");
        return (
          <div className="container">
            this is contentdiv>
    }
}

前面咱们介绍了虚拟 DOM、组件化,倘若把这两块知识整合一下,你就会发现这两个概念似乎都在围着 render 这个生命周期打转:虚拟 DOM 自然不必多说,它的生成都要仰仗 render;而组件化概念中所提及的“渲染工作流”,这里指的是从组件数据改变到组件实际更新发生的过程,这个过程的实现同样离不开 render。

由此看来,render 方法在整个组件生命周期中确实举足轻重,它担得起“灵魂”这个有分量的比喻。那么如果将 render 方法比作组件的“灵魂”,render 之外的生命周期方法就完全可以理解为是组件的“躯干”。

“躯干”未必总是会做具体的事情(比如说我们可以选择性地省略对 render 之外的任何生命周期方法内容的编写),而“灵魂”却总是充实的(render 函数却坚决不能省略);倘若“躯干”做了点什么,往往都会直接或间接地影响到“灵魂”(因为即便是 render 之外的生命周期逻辑,也大部分是在为 render 层面的效果服务);“躯干”和“灵魂”一起,共同构成了 React 组件完整而不可分割的“生命时间轴”。

拆解React生命周期:从React15说起

76527e3d999c95332bf0d9752dc909b2.png
Mounting 阶段:组件的初始化渲染(挂载)

挂载过程在组件的一生中仅会发生一次,在这个过程中,组件被初始化,然后会被渲染到真实 DOM 里,完成所谓的“首次渲染”。

在挂载阶段,一个 React 组件会按照顺序经历如下图所示的生命周期:

5dd1450bb9f5606579f9158b648a188a.png

首先我们来看 constructor 方法,该方法仅仅在挂载的时候被调用一次,我们可以在该方法中对 this.state 进行初始化:

constructor(props) {
     
  console.log("进入constructor");
  super(props);
  // state 可以在 constructor 里初始化
  this.state = { text: "子组件的文本" };
}

componentWillMount、componentDidMount 方法同样只会在挂载阶段被调用一次。其中 componentWillMount 会在执行 render 方法前被触发,一些同学习惯在这个方法里做一些初始化的操作,但这些操作往往会伴随一些风险或者说不必要性(这一点大家先建立认知)。

接下来 render 方法被触发。注意 render 在执行过程中并不会去操作真实 DOM(也就是说不会渲染),它的职能是「把需要渲染的内容返回出来」。真实 DOM 的渲染工作,在挂载阶段是由 ReactDOM.render 来承接的。

componentDidMount 方法在渲染结束后被触发,此时因为真实 DOM 已经挂载到了页面上,我们可以在这个生命周期里执行真实 DOM 相关的操作。此外,类似于异步请求、数据初始化这样的操作也大可以放在这个生命周期来做(侧面印证了 componentWillMount 真的很鸡肋)。

这一整个流程对应的其实就是我们 Demo 页面刚刚打开时,组件完成初始化渲染的过程。下图是 Demo 中的 LifeCycle 组件在挂载过程中控制台的输出,你可以用它来验证挂载过程中生命周期顺序的正确性:

b8f370b86c273e6bc4d61048b5d28c7a.png
Updating 阶段:组件的更新

组件的更新分为两种:一种是由父组件更新触发的更新;另一种是组件自身调用自己的 setState 触发的更新。这两种更新对应的生命周期流程如下图所示:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值