响应式系统与React | 青训营笔记

88 阅读6分钟

这是我参与「第四届青训营 」笔记创作活动的的第14天

零. 前置知识

  1. HTML、JS、CSS基础
  2. 数据结构基础知识,如二叉树、深度遍历。
  3. 熟悉浏览器提供的DOM API,了解如何使用API修改DOM、更新UI。

一. React的历史与应用

应用:

  1. 前端应用开发
  2. 移动原生应用开发
  3. 桌面应用开发

历史:

  1. 2010年,Facebook在其php生态中,引入了xhp框架,首次引入了组合式组件的思想,启发了后来的React 的设计。
  2. 2011年,Jordan Walke创造了FaxJS,也就是后来的React原型。
  3. 2012年,在Facebook收购Instagram后,该FaxJS项目在内部得到使用,Jordan Walke基于FaxJS的经验,实现了React。
  4. 2013年,React正式开源,在2013 JSConf 上 Jordan Walke介绍了这款全新的框架。
  5. 2014年至今,生态大爆发,各种围绕React 的新工具/新框架开始涌现。

二. React的设计思路

1. 举例

如图所示,当下方两块选项改变,右上角需要随之改变,按照传统思路,需要再两块选项的回调函数里 添加修改后触发的回调函数 修改右上角。

  1. 状态更新,UI不会自动更新,需要手动地调用DOM进行更新。
  2. 欠缺基本的代码层面的封装和隔离,代码层面没有组件化。
  1. UI之间的数据依赖关系,需要手动维护,如果依赖链路长,则会遇到“Callback Hell”(回调地狱)。

2. 响应式与转换式系统

转换式系统:给定[输入]求解[输出],例如 编译器、数值计算。

响应式系统:监听事件消息驱动,例如 实时监控系统、UI界面。

3. 响应式编程

  1. 状态更新,UI自动更新。
  2. 前端代码组件化,可复用,可封装。
  3. 状态之间的互相依赖关系,只需声明即可。

4. 组件化与状态归属

左侧不是DOM树,DOM是浏览器内部的东西。JS只能通过DOM的API获取变量,JS内部不含有DOM变量。

当两个组件需要共享状态的时候,将状态上移,但如果是这样的话,很多状态都会放到root节点,失去了我们组件隔离的意义。

  1. 组件是组建的组合\原子的组合
  2. 组件内拥有状态,外部不可见
  3. 父组件可将状态传入组件内部

5. 组件设计

  1. 组件声明了状态和UI的映射。
  2. 组件有Props/State两种状态。(内部私有状态state,外部传入的props)
  3. “组件"可由其他组件拼装而成。

6. 生命周期

  1. Mounting 挂载时
  2. Updating 更新时
  3. Unmounting 销毁时

三. React (hooks)的写法

useState :传入状态初始值。返回一个状态和设置该状态的函数,用户可以通过调用该函数实现状态的修改。

useEffect:副作用,需要用useEffect。有两个参数,一个是函数,一个是数组。当第二个参数省略的时候,第一个函数只会在mount挂载的时候执行一次。

hooks:挂载到react生命周期上执行的函数。例如useState(),useEffect()。

hooks使用原则:不要在判断条件或循环内使用hooks函数。

四. React的实现

1. 问题

  1. JSX 不符合 JS 标准语法
  2. 返回的 JSX 发生改变时,如何更新 DOM
  3. State/Props更新时,要重新触发 render 函数

2. 解决

  1. transpile

这个语法只是虚拟的,最终会进行转义,最后还是会转义成JavaScript语法。

  1. 虚拟DOM

使用 虚拟DOM树 虚拟DOM树和真实的DOM树会建立一一对应的关系,当虚拟DOM树发生改变时,React会确保真实的DOM也发生相应的改变。

  1. diff 算法

如果将全部的DOM删除,再将所有DOM重新绘制,非常耗时,我们需要一个算法去对比新旧版本中有修改的部分,只对更改的DOM做更新。diff算法本身不能太耗时,我们希望diff尽可能小计算时间尽可能短。

DIFF:tradeoff问题

完美的 diff 算法需要的时间复杂度为 O(n^3),而React牺牲了理论最小的 Diff,换取了时间,得到了 O(n)的时间复杂度。虚拟的DOM修改状态后,类型会发生改变。

  1. 若真实的DOM和虚拟的DOM不同的类型会替换,然后会将类型不同的虚拟DOM子节点全部替换;
  2. 若类型相同的DOM元素,进行更新;
  3. 若同类型的组件元素,进行递归。

五. React状态管理库

状态管理库是React的核心功能,它可以将数据保存到状态管理库中,这样就不用将组件内的状态的改变用函数的方式来改变了。但是并不是所有的组件都适合用这种方式保存状态,例如自己写的小组件,可以被别人使用,作为组件,不可能将数据都保存到状态管理库中,因该是封装度高的,所有数据都在组件内部的。还有有一些数据因该只是组件内可见的,如果到了状态管理库中,就将数据变得所有组件都可见了,这是不安全的。

将状态抽离到UI外部进行统一管理。

  • store适合放置距离远的组件、需要所有组件共享的消息。
  • 判断状态是被整个APP拥有的还是被一个组件拥有的。
  • 登录用户的信息:用户名、用户头像等适合放到store。

react状态管理库:很大的状态机。不用纠结用哪个,用哪个都行。

状态机:当前状态,收到外部事件,迁移到下一个状态。

六. 应用级框架科普

  1. next.js

硅谷明星创业公司Vercel的 React开发框架,稳定,开发体验好,支持Unbundled Dev,sWC等,其同样有Serverless一键部署平台帮助开发者快速完成部署。口号是"Let's Make Web Faster”。

  1. modern.js

字节跳动Web Infra团队研发的全栈开发框架,内置了很多开箱即用的能力与最佳实践,可以减少很多调研选择工具的时间。

  1. blitz

无API思想的全栈开发框架,开发过程中无需写API调用与CRUD逻辑,适合前后端紧密结合的小团队项目。