React与响应式 | 青训营笔记

73 阅读6分钟

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

一、React 历史

  • 2010年Facebook在其php生态中,引入了xhp框架,首次引入了组合式组件的思想,启发了后来的React的设计
  • 2011年Jordan Walke 创造了FaxIS,也就是后来的 React原型
  • 2012年在Facebook 收购Instagram后,该FaxJS 项目在内部得到使用,Jordan Walke基于FaxJS 的经验,创造了React,在 Facebook 内部得到了广泛的应用
  • 2013年 React 正式开源

二、React的设计思想

2.1 传统开发痛点

我们来看传统 ui 编程的痛点,下面所展示的是一件商品信息,在右上角会存在一个商品的价格信息,但是商品的价格信息会依赖于商品规格,当商品规格发生改变时,与之对应的价格也会发生改变,如果在传统开发当中,我们可能会监听商品规格的改变,改变之后,重新计算商品价格,并且使用 js 的一些 api,将价格重新渲染到页面当中,这个过程是很复杂的,并且也很消耗性能,因为页面需要重新进行 ui 渲染

image.png

传统开发会具有如下痛点:

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

2.2 响应式与组件化

响应式主要分为如下三个步骤:

  • 发出事件
  • 执行其回调
  • 状态变更

然后 React 对其添加了一个新的步骤,那就是 UI更新 至此就实现了数据驱动视图的变化

下面我们来看一下,响应式与传统ui编程的区别

  • 状态更新,UI自动更新
    • 状态更新,UI不会自动更新,需要手动地调用DOM进行更新
  • 前端代码组件化,可复用,可封装
    • 欠缺基本的代码层面的封装和隔离,代码层面没有组件化
  • 状态之间的互相依赖关系,只需声明即可。
    • UI之间的数据依赖关系,需要手动维护,如果依赖链路长,则会遇到回调嵌套 “回调地狱”

此时,我们就可以将 传统开发转换为如下结构,这就是将传统开发转为组件式开发,通过一个个小组件从而可以拼凑出一个完整的组件,小组件从而可以被进行复用,比如下图的型号选择与颜色选择,这两个就可以抽离成两个组件,然后使用遍历的方式通过传入不同的 props 参数,从而展示不同的数据

image.png

image.png

组件化总结

  • 组件是组件的组合/原子组件
  • 组件内拥有状态,外部不可见
  • 父组件可将状态传入组件内部

2.3 状态管理

当页面被封装一个个小的组件的时候,就需要考虑另一个问题了,那就是状态也就是页面数据。拿上面例子来说,它会存在一个 价格 的状态,那么该状态应该分配给哪个组件呢?答案应该是这个商品详情的大盒子的,那么此时又会出现一个问题,如果是最大的盒子,那么里面的子元素需要共享此状态,父元素就需要通过 props 来把数据向下进行传递,如果子元素嵌套过多,就会发现需要传递很多层 props 最终的子元素才能拿到这个数据,那么如果不只是它的子元素需要这个状态呢,比如与它完全独立的支付页面也需要这个价格数据,那么此时怎么进行传递呢,此时就需要使用我们的状态管理的工具,来进行数据共享。

image.png 该图主要展示了通过状态管理和没有通过状态管理的区别,通过状态管理,我们的组件只需要跟该store来进行通信了,而不在需要根据 props 一层一层往下进行传递了。

那么现在又该思考了,什么时候使用状态管理呢?

这个答案肯定是不统一我,我就来说说我个人意见,当很多组件或者页面需要使用同一个状态时,就需要使用状态管理了,当然也不是只要一存在数据需要多个组件共享就一定使用状态管理,在react当中有 context 也是进行数据传递的,它需要将需要传递的数据给父组件,只要包含在该父组件内的所有子元素都可以获取到数据了,这个使用在数据共享少的地方使用,如果数据存在很多地方进行共享,那么还是使用 状态管理会更方便一点

三、react 响应式实现

当返回的 jsx 状态发生改变的时候,会重新执行 render 进行页面渲染,状态改变也需要使用特定的规则来改变

现在我们来看一下 jsx 转换之后的代码: image.png

此时我们应该思考,状态改变触发渲染机制,然后进行页面渲染,是怎么保证页面性能的呢? 答:采用虚拟 DOM 结合 diff 算法来实现,虚拟dom是与真实dom处于一一对应的关系,diff算法主要用于对比虚拟dom与真实dom哪些地方存在变化,这需要将存在变化的位置进行重新渲染,没有变化的就不需要重新渲染。

来看一段虚拟dom的介绍: Virtual DOM(虚拟DOM): Virtual DOM是一种用于和真实DOM同步,而在JS内存中维护的一个对象,它具有和DOM类似的树状结构,并和DOM可以建立一—对应的关系。

它赋予了React声明式的API:您告诉React希望让U是什么状态,React就确保DOM匹配该状态。这使您可以从属性操作、事件处理和手动DOM更新这些在构建应用程序时必要的操作中解放出来。

下图是diff对比过程 图一红色区域表示该元素已经改变了,然后通过diff与真实dom进行比对,会将该元素包含该元素的子元素,全部重新渲染,就得到了图三的结果,当然不是父元素只要改变了就会重新渲染里面的所有子元素,比如父元素属性改变等,这样只会更新父元素的某些属性,不会重新渲染父元素当中的所有子元素的,但是如果父元素 key 发生变化,或者父元素从本来的 div 元素改变成了 span 元素,这样才会导致子元素也会一起渲染

image.png

以上就是对 React 的基本介绍,react的内容还有很多,比如现在很火爆的 hooks,篇幅很长,我们可以参照官方文档进行学习,告辞, 啊哈哈哈~