一二一、React原理篇

React.setState

setState本质是通过一个队列机制实现state更新的。 执行setState时,会将需要更新的state合并后放入状态队列,而不会立刻更新state,队列机制可以批量更新state。
如果不通过setState而直接修改this.state,那么这个state不会放入状态队列中,下次调用setState时对状态队列进行合并时,会忽略之前直接被修改的state,这样我们就无法合并了,而且实际也没有把你想要的state更新上去。

在这里插入图片描述

  • 在官方的描述中,setState操作并不保证是同步的,也可以认为是异步的。

  • React在setState之后,会经对state进行diff,判断是否有改变,然后去diff dom决定是否要更新UI。如果这一系列过程立刻发生在每一个setState之后,就可能会有性能问题。

  • 在短时间内频繁setState。React会将state的改变压入栈中,在合适的时机,批量更新state和视图,达到提高性能的效果。

  • 如何知道state已经被更新

    1. 回调函数
    2. componentDidUpdate
    3. promise封装 通过async await

Virtual DOM

Virtual DOM 是一个轻量级的 JavaScript 对象,它最初只是 real DOM 的副本。它是一个节点树,它将元素、它们的属性和内容作为对象及其属性。 React 的渲染函数从 React 组件中创建一个节点树。然后它响应数据模型中的变化来更新该树,该变化是由用户或系统完成的各种动作引起的。

  1. 每当底层数据发生改变时,整个 UI 都将在 Virtual DOM 描述中重新渲染。
  2. 然后计算之前 DOM 表示与新表示的之间的差异。

    key 用于识别唯一的 Virtual DOM 元素及其驱动 UI 的相应数据。它们通过回收 DOM 中当前所有的元素来帮助 React 优化渲染。这些 key 必须是唯一的数字或字符串,React 只是重新排序元素而不是重新渲染它们。这可以提高应用程序的性能。

  3. 完成计算后,将只用实际更改的内容更新 real DOM。

React 组件的生命周期方法

  • componentWillMount**()** – 在渲染之前执行,在客户端和服务器端都会执行。
  • componentDidMount**()** – 仅在第一次渲染后在客户端执行。
  • componentWillReceiveProps**()** – 当从父类接收到 props 并且在调用另一个渲染器之前调用。
  • shouldComponentUpdate**()** – 根据特定条件返回 true 或 false。如果你希望更新组件,请返回true 否则返回 false。默认情况下,它返回 false。
  • componentWillUpdate**()** – 在 DOM 中进行渲染之前调用。
  • componentDidUpdate**()** – 在渲染发生后立即调用。
  • componentWillUnmount**()** – 从 DOM 卸载组件后调用。用于清理内存空间。

高阶组件(HOC)

高阶组件是重用组件逻辑的高级方法,是一种源于 React 的组件模式。 HOC 是自定义组件,在它之内包含另一个组件。它们可以接受子组件提供的任何动态,但不会修改或复制其输入组件中的任何行为。

作用

  • 代码重用,逻辑和引导抽象
  • 渲染劫持
  • 状态抽象和控制
  • Props 控制

Redux遵循的三个原则

  1. ***单一事实来源:***整个应用的状态存储在单个 store 中的对象/状态树里。单一状态树可以更容易地跟踪随时间的变化,并调试或检查应用程序。

    Mobx则通常按模块将应用状态划分,在多个独立的store中管理

  2. ***状态是只读的:***改变状态的唯一方法是去触发一个动作。动作是描述变化的普通 JS 对象。就像 state 是数据的最小表示一样,该操作是对数据更改的最小表示。

    Mobx中直接使用新值更新状态对象

  3. ***使用纯函数进行更改:***为了指定状态树如何通过操作进行转换,你需要纯函数。纯函数是那些返回值仅取决于其参数值的函数。

    Mobx使用inject将特定的store注入组件,store可以传递状态或action, 然后使用observer保证组件能响应store中的客观查对象observable变更,即store更新,组件视图响应式更新

React Fiber

React Fiber 原理介绍

  1. reqct 15的问题

    • 在页面元素很多,且需要频繁刷新的场景下,React 15 会出现掉帧的现象
    • 其根本原因,是大量的同步计算任务阻塞了浏览器的 UI 渲染。默认情况下,JS 运算、页面布局和页面绘制都是运行在浏览器的主线程当中,他们之间是互斥的关系。如果 JS 运算持续占用主线程,页面就没法得到及时的更新。当我们调用setState更新页面的时候,React 会遍历应用的所有节点,计算出差异,然后再更新 UI。整个过程是一气呵成,不能被打断的。如果页面元素很多,整个过程占用的时机就可能超过 16 毫秒,就容易出现掉帧的现象。
  2. 解决思路

    • 解决主线程长时间被 JS 运算占用这一问题的基本思路,是将运算切割为多个步骤,分批完成。也就是说在完成一部分任务之后,将控制权交回给浏览器,让浏览器有时间进行页面的渲染。等浏览器忙完之后,再继续之前未完成的任务。
    • 旧版 React 通过递归的方式进行渲染,使用的是 JS 引擎自身的函数调用栈,它会一直执行到栈空为止。而Fiber实现了自己的组件调用栈,它以链表的形式遍历组件树,可以灵活的暂停、继续和丢弃执行的任务。实现方式是使用了浏览器的requestIdleCallback这一 API。

    window.requestIdleCallback()会在浏览器空闲时期依次调用函数,这就可以让开发者在主事件循环中执行后台或低优先级的任务,而且不会对像动画和用户交互这些延迟触发但关键的事件产生影响。函数一般会按先进先调用的顺序执行,除非函数在浏览器调用它之前就到了它的超时时间。

  3. react 实现

    1. React 框架内部的运作可以分为 3 层:
      Virtual DOM 层,描述页面长什么样。
      Reconciler (调解)层,负责调用组件生命周期方法,进行 Diff 运算等。
      Renderer 层,根据不同的平台,渲染出相应的页面,比较常见的是 ReactDOM 和 ReactNative。
    2. Reconciler > Fiber Reconciler
      阶段一,生成 Fiber 树,得出需要更新的节点信息。这一步是一个渐进的过程,可以被打断。
      阶段二,将需要更新的节点一次过批量更新,这个过程不能被打断。

    阶段一可被打断的特性,让优先级更高的任务先执行,从框架层面大大降低了页面掉帧的概率。

  4. Fiber 树

Fiber Reconciler 在阶段一进行 Diff 计算的时候,会生成一棵 Fiber 树。这棵树是在 Virtual DOM 树的基础上增加额外的信息来生成的,它本质来说是一个链表。

  1. Fiber 树在首次渲染的时候会一次过生成。在后续需要 Diff 的时候,会根据已有树和最新 Virtual DOM 的信息,生成一棵新的树。这颗新树每生成一个新的节点,都会将控制权交回给主线程,去检查有没有优先级更高的任务需要执行。如果没有,则继续构建树的过程
  2. 如果过程中有优先级更高的任务需要进行,则 Fiber Reconciler 会丢弃正在生成的树,在空闲的时候再重新执行一遍。

react Hooks

react hooks
优点:

  1. 更容易复用代码

    把"useTable"和输出的值写到一起,结构更清晰,更容易阅读和维护。
    对比高阶组件,代码量更少。

  2. 清爽的代码风格

    函数式编程风格,函数式组件、状态保存在运行环境、每个功能都包裹在函数中,整体风格更清爽,更优雅。另外,对比类组件,函数组件里面的unused状态和unused-method更容易被发现。

  3. 代码量更少

    向props或状态取值更加方便,函数组件的取值都从当前作用域直接获取变量,而类组件需要先访问实例引用this,再访问其属性或者方法,多了一步。
    更改状态也变得更加简单, this.setState({ count:xxx })变成 setCount(xxx)。
    因为减少了很多模板代码,特别是小组件写起来更加省事,人们更愿意去拆分组件。而组件粒度越细,则被复用的可能性越大。所以,hooks也在不知不觉中改变人们的开发习惯,提高项目的组件复用率。

缺点:

  1. 响应式的useEffect

    必须清楚代码中useEffect和useCallback等api的第二个参数“依赖项数组”的改变时机,并且掌握上下文的useEffect的触发时机。当逻辑较复杂的时候,useEffect触发的次数,可能会被你预想的多。对比componentDidmount和componentDidUpdate,useEffect带来的心智负担更大。

  2. 状态不同步

    React Hooks 中存在 Capture Value 的特性(可以使用useRef解决)

  3. 复杂业务的时候,使用Component代替hooks
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值