响应式系统与React | 青训营笔记
这是我参与「第四届青训营 」笔记创作活动的第11天 与大家分享响应式系统与React的基础知识,包括React的发展、概念、应用等,不足之处欢迎大家批评指正!
React的历史与应用
应用场景
01 前端应用开发
如facebook,Instagram,Netflix网页版
02 移动原生应用开发
如Instagram,Discord,Oculus
03 桌面应用开发
结合Electron
React历史
2010年
Facebook在其php生态中,引入了xhp框架,首次引入组合式组件的思想,启发了后来的React设计
React的设计思路
UI编程痛点
更改颜色的同时更改右上角的价格
设计痛点:
-
状态更新,UI不会自动更新,需要手动地调用DOM进行更新
-
欠缺基本的代码层面的封装和隔离,代码层面没有组件化
-
UI之间的数据依赖关系,需要手动维护,如果依赖链路长,则会遇到"Callback Hell"。
响应式与转换式
转换式系统:给定输入求解输出的过程
响应式系统:监听事件,异步操作,消息驱动。
- 响应式系统
响应式编程
相比原来的优点:
01 状态更新,UI自动更新
02 前端代码组件化,可复用,可封装
03 状态之间的相互依赖关系,只需声明即可
- 前端UI
React的设计与实现
组件化
整个页面:Root组件
组件划分:自己划分
- 总结
- 组件是组件的组合/原子组件
- 组件内拥有状态,外部不可见
- 父组件可将状态传入组件内部
状态归属问题
“当前价格”状态:属于Root节点!状态归属于两个节点向上找到最近的祖宗节点
当前价格状态如何改变:将onChangeValue()向下传递
React是单向数据流:只能父组件给子组件传东西,子组件可以改变父组件的状态
组件化设计思路
组件设计
- 组件声明了状态和UI的映射
- 组件有Props/State两种状态
- “组件”可由其他组件拼接而成
响应式编程设计思路
React生命周期
-
Mounting 显示在UI上,要挂载到实际DOM上
-
Updating
render:每当事件发生改变setState(),要重新执行函数,更新UI
React updates DOM and refs:更新真实DOM的阶段
结束后:执行componentDidMount
- Unmounting 卸载
React(hooks)的写法
- useEffect
useEffect:传入一个函数,和一个数组,称作依赖项,该函数在mount时,和依赖项被set的时候回执行。
有“副作用”的函数,要传入useEffect来执行。副作用代表除了单纯的计算之外,还要做一些其他事情,比如网络请求,更新DOM,localStorage存储数据等
- Hook使用法则
不要在循环、条件或嵌套函数中调用Hook
React的实现
问题
01 JSX不符合JS标准语法
02返回的JSX发生改变时如何更新DOM
03 State/Props更新时,要重新触发render函数
- 问题1
不同语言的语法转变时,JSX不符合JS标准语法
- 问题2 Virtual DOM(虚拟DOM)
Virtual DOM是一种用于和真实DOM同步,而在JS内存中维护的一个对象,它具有和DOM类似的树状结构,并和DOM可以建立一一对应的关系。
真实的DOM不是JS中的对象,是浏览器内部维护的状态,只能通过DOM接口去修改,可以设定一个Virtual DOM
它赋予了React声明式的API:您告诉React希望让UI是什么状态,React就确保DOM匹配该状态。这使您可以从属性操作、事件处理和手动DOM更新这些在构建应用程序时必要的操作中解放出来。
上部分:虚拟DOM
状态发生改变,虚拟DOM新的和旧的发生Diffing过程,递归发生render,实现Re-render
下部分:实际DOM
How to Diff?
render函数本身:执行、计算速度快
DOM:更新次数少
TradeOff:权衡
完美的小Diff算法,需要
O(n^3)的复杂度
牺牲理论最小Diff,不一定是全局最优,可能是局部最优,换取时间,得到O(n)复杂度的算法
Heuristic O(n) Algorithm
React状态管理库
- 核心思想 将状态抽离到UI外部进行统一管理
- 缺点 降低组件复用性
- 适用
store:最好放距离比较远、需要共享的状态,应用层级别,状态是被整个up所拥有的,而不是某个组件所拥有的,比如当前用户的头像、用户信息等等
推荐
状态机
事件 -> 状态机 -> 状态机根据当前状态,收到外部事件,迁移到下一个状态
应用级框架科普
- 功能展示