这是我参与「第四届青训营 」笔记创作活动的的第9天
前置知识
- HTML, JS, CSS
- 基础的数据结构/算法知识, 如二叉树, 深度遍历等
- 会使用浏览器提供的DOM API修改DOM, 更新UI
01 React 的历史与应用
应用
- 前端应用开发
- 移动原生应用开发
- 结合Electron, 进行桌面应用开发
历史
2010年 Facebook在其php生态中, 引入了xhp框架, 首次引入了组合式组件的思想, 启发了后来的React的设计
2011年 Jordan Walke创造了FaxJS, 也就是后来的React原型
2012年 在Facebook收购Instagram后, 该FaxJS项目在内部得到使用, Jordan Walke基于FaxJS的经验, 创造了React
2013年 React正式开源
02 React 的设计思路
UI编程痛点
- 状态更新, UI不会自动更新, 需要手动地调用DOM进行更新
- 欠缺基本的代码层面的封装和隔离, 代码层面没有组件化
- UI之间的数据依赖关系, 需要收到维护, 如果依赖链路长, 则会遇到"Callback Hell"
转化式系统与转换式
转换式系统
- 给定[输入]求解[输出]
响应式系统
- 监听事件
- 消息驱动
- 事件 -> 执行既定的回调 -> 状态变更
前端
- 事件 -> 执行既定的回调 -> 状态变更 -> UI更新
- 状态更新, UI自动更新
- 前端代码组件化, 可复用, 可封装
- 状态之间的互相依赖关系, 只需声明即可
组件化
- 组件是组件的组合或原子组件
- 组件内拥有状态, 外部不可见
- 父组件可将状态传入组件内部
思考
-
React 是单向数据流, 还是双向数据流?
单向, 永远都是父组件向子组件传递数据. 但这不代表子组件不能改变父组件状态, 父组件可以通过传递函数给子组件, 实现子组件改变父组件状态
-
如何解决状态不合理上升的问题?
可以通过状态管理库解决 见05 React状态管理库
-
组件的状态改变后, 如何更新DOM?
见04 React的实现
组件设计
- 组件声明了状态和UI的映射
- 组件有Props/State两种状态
- "组件可由其他组件拼接而成"
思路
- 组件内部拥有私有状态State
- 组件接受外部的Props状态提供复用性
- 根据当前的State/Props, 返回一个UI
生命周期
Mounting 挂载
Updating 更新
Unmounting 卸载
03 React (hooks)的写法
useState
useEffect
⭐不要在循环, 条件或嵌套函数中调用hook
04 React 的实现
问题
-
JSX不符合JS标准语法
转义
-
返回的JSX发生改变时, 如何更新DOM
通过Virtual DOM (虚拟DOM)
是一种用于和真实DOM同步, 而在JS内存中维护的一个对象, 它具有和DOM类似的树状结构, 并和DOM可以建立一一对应的关系
Change of State => Diffing => Re-render Virtual DOM
-
State/Props更新时, 要重新触发render函数
How to Diff? (更新次数少 TradeOff 计算速度快)
完美的最小Diff算法, 复杂度O(n^3)
牺牲理论最小Diff, 换取时间, 得到O(n)复杂度的算法: Heuristic O(n) Algorithm
Heuristic: 启发式的. (不一定对, 感觉上是对的)
- 不同类型的元素: 替换
- 同类型的DOM元素 更新
- 同类型的组件元素 递归
弊病: 当一个父组件状态改变, 所有子节点会递归render, 影响性能
05 React 状态管理库
核心思想: 将状态抽离到UI外部进行统一管理 ⭐
缺点: 降低组件的复用性, 增加耦合
因此组件库是不会用状态管理库, 一般业务代码才会用
一些状态管理库: redux, xstate, mobx, recoil
状态机: 当前状态, 收到外部事件, 迁移到下一个状态
06 应用级框架科普
- NEXT.js
- MODERN.js
- Blitz