1. React 简介与特性
React:用于构建用户界面的 JavaScript 库
1.1 React 特点
- 声明式设计 −React 采用声明范式,可以轻松描述应用。
- 高效 −React 通过对 DOM 的模拟,最大限度地减少与 DOM 的交互。
- 灵活 −React 可以与已知的库或框架很好地配合。
- JSX − JSX 是 JavaScript 语法的扩展。React 开发不一定使用 JSX ,但我们建议使用它。
- 组件 − 通过 React 构建组件,使得代码更加容易得到复用,能够很好的应用在大项目的开发中。
- 单向响应的数据流 − React 实现了单向响应的数据流,从而减少了重复代码,这也是它为什么比传统数据绑定更简单。
- 跨平台编写
1.2 React 哲学
React 是用 JavaScript 构建快速响应的大型 Web 应用程序的首选方式之一。它在 Facebook 和 Instagram 上表现优秀。
等待资源加载时间和大部分情况下浏览器单线程执行是影响 web 性能的两大主要原因。
等待资源加载
- 一次请求太多资源
- 网络请求慢
- 资源加载失败
React.Lazy
React.Suspense
ErrorBoundary
浏览器线程执行
- JS 执行
- 浏览器计算样式布局
- UI 绘制
异步更新
时间切片
React Fiber
1.2.1 更新流程
Scheduler(调度器)
- 维护时间切片
- 与浏览器任务调度
- 优先级调度
Reconciler(协调器)
- 将 JSX 转化为 Fiber
- Fiber 树对比(双缓存)
- 确定本次更新的 Fiber
Renderer(渲染器)
- 渲染器用于管理一棵 React 树
- 使其根据底层平台进行不同的调用
1.3 总结
优点
- 快速响应:Fiber
- 组件化:复用性强
- 声明式编程
- 跨平台:只需修改渲染器
缺点
- 大型应用需要配套学习状态管理、路由工具
- 不适合小型应用,需要用 babel 处理
2. React 基础温故知新
2.1 用 React 开发 web 应用
架构
打包配置:JSX->babel->JS
加载优化和错误降级
路由
React Router 向应用中快速地添加视图和数据流,保持页面与 URL 间的同步
UI
可复用 UI->组件->页面
可复用逻辑抽离成 hook
状态
多页面多组件共享信息 redux & context
2.2 组件
数据
通过定义 state 操作视图 Mount 时获取数据更新 state
Ref 保存与视图无直接关系的值 unMount 前清空 Ref
通信
props 父子组件通信
context & redux 组件信息共享
UI
数据决定视图
通过 Ref 获取到 DOM
性能
函数使用 useCallback 值或计算使用 useMemo 组件包裹 memo
2.2.1 Class 组件
- 继承 + 构造函数
- this
- 生命周期
- render 方法
2.2.2 函数式组件
- 没有生命周期
- 借助 Hook
- return JSX
函数式相较于 Class 的优点
- 代码量骤减,组件干净清爽
- 没有复杂的生命周期
- 支持自定义 hook,逻辑复用方便
组件和 Hook 的关系
- 我们将 UI 拆成多个独立单元,这些单元组合可以构成多种视图展示,这些独立单元就是组件。组件相当于原子
- hook 贴近组件内部运行的各种概念逻辑,effect、state、context等。hooks 更贴切于电子
2.3 Hook
2.3.1 规则 & 原理
只能在最顶层使用 Hook
React 靠 Hook 调用顺序知道哪个 state 对应哪个 useState。
只能在 React 函数中调用 Hook
- 在 React 函数组件中或自定义 Hook 中调用
- 自定义 Hook 必须以 use 开头
- Hook 中的 state 是完全隔离的
2.3.2 过期闭包问题
在 JS 中,函数运行的上下文是由定义的位置决定的,当函数的闭包包住了旧的变量值时,就出现了过期闭包问题。
2.4 常见 API 及作用
| React.COmponent | 类组件基类 extends |
|---|---|
| React.PureComponent | 为实现 shouldComponentUpdate(),内置了 props 和 state 浅层对比 |
| React.memo | 高阶组件,仅比较 props 变更 |
| React.createElement | 创建并返回 React 元素,不使用 JSX 场景 |
| React.cloneElement | 克隆并返回新 React 元素,并且可以为新元素添加额外 props |
| React.Children.[Fn] | map 遍历并返回;forEach 仅遍历;count 子组件数量;only 是否只有一个子节点 |
| React.createRef | 创建一个 ref,并附加到具体元素上,class 组件中获取 dom 结构常用 |
| React.forwardRef | 转发 ref 或者与 useImperativeHandler 联合使用暴露方法 |
| React.lazy | 实现组件动态加载 |
| React.Suspense | 组件加载过程优雅降级 |
2.5 常见 Hook 及作用
| useState | 返回一个 state 及更新 state 的函数 |
|---|---|
| useEffect | 可以让你在函数组件中执行某些操作,挂载时、依赖变化时甚至说卸载前 |
| useContext | 接收最近的上层 context 对象,并返回其值,一般与 createContext 一起使用 |
| useRef | 返回一个可变的 ref 对象,在组件生命周期内持续存在 |
| useMemo | 参数为计算函数和依赖项,只有在依赖项变化时才调用计算函数,返回函数的计算值 |
| useCallback | useCallback(fn,deps),相当于 useMemo(()=>fn,deps),一般返回的是一个新函数 |
| useRender | useState 的更丰富替代方案,返回 [state,dispatch],这里 state 可以是复杂对象,dispatch 可以更新这个复杂对象 |
| useImperativeHandler | 可以给父组件暴露方法,一般与 forwardRef 一起使用 |
| useLayoutEffect | useEffect 的执行时机是浏览器完成渲染之后,而 useLayoutEffect 的执行时机是浏览器把内容真正渲染到界面之前,是和 componentDidMount 等价的 |