这是我参与「第四届青训营 」笔记创作活动的第2天。
写在前面
大多数人在入门前端三大件之后,可能大都会学习vue,另外在vue在培训班当中也十分热门。是什么原因让react在国内稍微遇冷,而在大厂的使用当中react仍占大多数呢?作为一门在国际主流的语言
React,或许在中文文档领域上不如vue,前期学习成本相比起vue肯可能会更陡峭。然而笔者更喜欢react,因为react的jsx(tsx)更接近js原生的感觉,从组件结构上可以更高效,下面在学习完课程之后,记下一些知识点和自己的理解。
开始之前推荐大家一个Google的插件Wappalyzer用于分析页面的框架使用结果。
重新认识React
在React官网中,有这么一句话
React: A JavaScript library for building user interfaces
在设计之初,开发者就给react这样一个定义。
相比于UI编程会,react设计思路会有什么亮点呢?
从传统的UI编程来看,顺序是这样的
- 用户触发按钮
- 数据改变-代码没有组件化
- UI改变-手动调用DOM
响应式与转换式
从一些基本的转换式逻辑来看,往往是给定特定的输入从而求解出输出,这样的逻辑往往会用在编译器上和数值计算中。那么这样的转换式的系统逻辑,往往在前端来看并不合适,前端逻辑反而是
事件E->回调C->状态S
即类似于监控一样的响应式范式。
面向这样的需求,前端工程师需要一套编程模式,进而实现
- 状态更新,UI更新
- 组件可复用、封装
- 声明式依赖关系
组件化和状态归属
比如说这个水果官网的页面,我们为了方便开发,将其语义化后则为上面的树节点。
那么其中的每一个子组件,可以视作为原子组件,维护自己的状态,不同组件之间相互隔离状态又相互联通。
具体一点则是:
作为一个消费者购买商品的时候,触发的选择,状态属于谁呢?
因为我们父组件可以控制子组件,像这样的一种情况,当前的价格是属于Root父组件,因为是从上往下进行传递的。当两个组件需要共享的时候,状态节点可以上移。
但是这时候可能有人会想,如果状态特别多,那么Root父组件状态管理岂不是很复杂,这个留一个疑问,后面将会回答
我们希望组件有自己的状态和UI映射,另外有Props和state两种状态,以及可以由其他原子组件构成。
生命周期
说到组件的生命周期,往往会涉及到React Hooks。在这里除了常用的库函数,除了setState(), useEffet(),还会有其他如useMemo()等。因为React Hook可以作为单独一章,在此处不展开。
React的实现
React的JSX或TSX十分接近原始的写法,其创建的虚拟DOM笔者看来有类似于一个object。
JSX
首先对于JSX来说,会面临这些问题。
- JSX不符合JS标准
- JS改变的时候怎么执行DOM
JSX不符合标准的问题可以通过编译解决,而JS改变的时候渲染的DOM则是通过虚拟DOM来实现->通过diff算法计算出different的部分render。
那么React怎么实现状态管理呢?
状态改变实现
更新DOM是一个比较复杂的东西,如果重新render整一个DOM则会十分消耗性能。
这时候我们需要在更新速度和计算速度中找到一个权衡。
所以react采用的是visualDOM,并且通过diff算法求Diff差异部分,返回最优的结果。
React 通过制定大胆的策略,将 O(n^3) 复杂度的问题转换成 O(n) 复杂度的问题,最终的实现总结如下图。
但是具体的转换过程还会涉及深度优先遍历等,则不再赘述。
React状态管理
所谓状态管理,也就是一个props传递的过程,对于React的状态管理,核心即是将状态抽离到UI外部进行统一管理。
但是显然,这样会影响组件的复用性,那么在工程实践当中,需要组件进行状态共享时,即可以放在更上层的UI。另外还有许多优秀的状态管理库,用于维护其中的状态。
状态管理库
参考
- React探索-diff算法 zhuanlan.zhihu.com/p/103187276